home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / gas / src138.zoo / vms.c < prev    next >
C/C++ Source or Header  |  1991-01-21  |  71KB  |  3,088 lines

  1. /* vms.c -- Write out a VAX/VMS object file
  2.    Copyright (C) 1987, 1988 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* Written by David L. Kashtan */
  21. #include <ctype.h>
  22. #include <stdio.h>
  23. #include "as.h"
  24. #include "md.h"
  25. #include "subsegs.h"
  26. #include "obstack.h"
  27. #include "struc-symbol.h"
  28. #include "write.h"
  29. #include "symbols.h"
  30.  
  31. #ifdef    VMS        /* THIS MODULE IS FOR VMS ONLY */
  32.  
  33. #include <stab.h>
  34. #include "objrecdef.h"            /* Define VMS Object record lang. */
  35. #include <vms/fabdef.h>            /* Define File Access Block      */
  36. #include <vms/namdef.h>            /* Define NAM Block          */
  37. #include <vms/xabdef.h>            /* Define XAB              */
  38. #include <vms/xabdatdef.h>        /* Define Date XAB          */
  39. #include <vms/xabfhcdef.h>        /* Define File Header XAB      */
  40.  
  41. /*
  42.  *    Version string of the compiler that produced the code we are
  43.  *    assembling.  (And this assembler, if we do not have compiler info.)
  44.  */
  45. extern char version_string[];
  46. char *compiler_version_string;
  47.  
  48. extern char *myname;
  49. static symbolS *Entry_Point_Symbol = 0;    /* Pointer to "_main"     */
  50.  
  51. /*
  52.  *    We augment the "gas" symbol structure with this
  53.  */
  54. struct VMS_Symbol {
  55.     struct VMS_Symbol *Next;
  56.     struct symbol *Symbol;
  57.     int Size;
  58.     int Psect_Index;
  59.     int Psect_Offset;
  60.     };
  61. struct VMS_Symbol *VMS_Symbols = 0;
  62.  
  63. /* we need this to keep track of the various input files, so that we can
  64.  * give the debugger the correct source line 
  65.  */
  66.  
  67. struct input_file{
  68.     struct input_file* next;
  69.     struct input_file* same_file_fpnt;
  70.     int file_number;
  71.     int max_line;
  72.     int min_line;
  73.     int offset;
  74.     char flag;
  75.     char * name;
  76.     symbolS * spnt;
  77.     };
  78.  
  79. static struct input_file * file_root = (struct input_file*)NULL;
  80.  
  81. struct input_file * find_file(symbolS *);
  82.  
  83.  
  84. /*
  85.  *    If the procedure "main()" exists we have to add the instruction
  86.  *    "jsb c$main_args" at the beginning to be compatible with VAX-11 "C".
  87.  */
  88. VMS_Check_For_Main()
  89. {
  90.   register symbolS *symbolP;
  91. #ifdef    HACK_DEC_C_STARTUP    /* JF */
  92.   register struct frchain *frchainP;
  93.   register fragS *fragP;
  94.   register fragS **prev_fragPP;
  95.   register struct fix *fixP;
  96.   register fragS *New_Frag;
  97.   int i;
  98. #endif    HACK_DEC_C_STARTUP
  99.  
  100.   symbolP = (struct symbol *)symbol_find("_main");
  101.   if (symbolP && (symbolP->sy_nlist.n_type == (N_TEXT | N_EXT))) {
  102. #ifdef    HACK_DEC_C_STARTUP
  103.     if( !flagseen['+']) {
  104. #endif
  105.         /*
  106.          *    Remember the entry point symbol
  107.          */
  108.         Entry_Point_Symbol = symbolP;
  109. #ifdef HACK_DEC_C_STARTUP
  110.     } else {
  111.         /*
  112.          *    Scan all the fragment chains for the one with "_main"
  113.          *    (Actually we know the fragment from the symbol, but we need
  114.          *     the previous fragment so we can change its pointer)
  115.          */
  116.         frchainP = frchain_root;
  117.         while(frchainP) {
  118.             /*
  119.              *    Scan all the fragments in this chain, remembering
  120.              *    the "previous fragment"
  121.              */
  122.             prev_fragPP = &frchainP->frch_root;
  123.             fragP = frchainP->frch_root;
  124.             while(fragP && (fragP != frchainP->frch_last)) {
  125.                 /*
  126.                  *    Is this the fragment?
  127.                  */
  128.                 if (fragP == symbolP->sy_frag) {
  129.                     /*
  130.                      *    Yes: Modify the fragment by replacing
  131.                      *         it with a new fragment.
  132.                      */
  133.                     New_Frag = (fragS *)
  134.                         xmalloc(sizeof(*New_Frag) +
  135.                                 fragP->fr_fix +
  136.                                 fragP->fr_var +
  137.                                 5);
  138.                     /*
  139.                      *    The fragments are the same except
  140.                      *    that the "fixed" area is larger
  141.                      */
  142.                     *New_Frag = *fragP;
  143.                     New_Frag->fr_fix += 6;
  144.                     /*
  145.                      *    Copy the literal data opening a hole
  146.                      *    2 bytes after "_main" (i.e. just after
  147.                      *    the entry mask).  Into which we place
  148.                      *    the JSB instruction.
  149.                      */
  150.                     New_Frag->fr_literal[0] = fragP->fr_literal[0];
  151.                     New_Frag->fr_literal[1] = fragP->fr_literal[1];
  152.                     New_Frag->fr_literal[2] = 0x16; /* Jsb */
  153.                     New_Frag->fr_literal[3] = 0xef;
  154.                     New_Frag->fr_literal[4] = 0;
  155.                     New_Frag->fr_literal[5] = 0;
  156.                     New_Frag->fr_literal[6] = 0;
  157.                     New_Frag->fr_literal[7] = 0;
  158.                     for(i = 2; i < fragP->fr_fix + fragP->fr_var; i++)
  159.                         New_Frag->fr_literal[i+6] =
  160.                             fragP->fr_literal[i];
  161.                     /*
  162.                      *    Now replace the old fragment with the
  163.                      *    newly generated one.
  164.                      */
  165.                     *prev_fragPP = New_Frag;
  166.                     /*
  167.                      *    Remember the entry point symbol
  168.                      */
  169.                     Entry_Point_Symbol = symbolP;
  170.                     /*
  171.                      *    Scan the text area fixup structures
  172.                      *    as offsets in the fragment may have
  173.                      *    changed
  174.                      */
  175.                     for(fixP = text_fix_root; fixP; fixP = fixP->fx_next) {
  176.                         /*
  177.                          *    Look for references to this
  178.                          *    fragment.
  179.                          */
  180.                         if (fixP->fx_frag == fragP) {
  181.                             /*
  182.                              *    Change the fragment
  183.                              *    pointer
  184.                              */
  185.                             fixP->fx_frag = New_Frag;
  186.                             /*
  187.                              *    If the offset is after
  188.                              *    the entry mask we need
  189.                              *    to account for the JSB
  190.                              *    instruction we just
  191.                              *    inserted.
  192.                              */
  193.                             if (fixP->fx_where >= 2)
  194.                                 fixP->fx_where += 6;
  195.                         }
  196.                     }
  197.                     /*
  198.                      *    Scan the symbols as offsets in the
  199.                      *    fragment may have changed
  200.                      */
  201.                     for(symbolP = symbol_rootP;
  202.                         symbolP;
  203.                         symbolP = symbolP->sy_next) {
  204.                         /*
  205.                          *    Look for references to this
  206.                          *    fragment.
  207.                          */
  208.                         if (symbolP->sy_frag == fragP) {
  209.                             /*
  210.                              *    Change the fragment
  211.                              *    pointer
  212.                              */
  213.                             symbolP->sy_frag = New_Frag;
  214.                             /*
  215.                              *    If the offset is after
  216.                              *    the entry mask we need
  217.                              *    to account for the JSB
  218.                              *    instruction we just
  219.                              *    inserted.
  220.                              */
  221.                             if (symbolP->sy_nlist.n_value >= 2)
  222.                                 symbolP->sy_nlist.n_value += 6;
  223.                         }
  224.                     }
  225.                     /*
  226.                      *    Make a symbol reference to
  227.                      *    "_c$main_args" so we can get
  228.                      *    its address inserted into the
  229.                      *    JSB instruction.
  230.                      */
  231.                     symbolP = (symbolS *)xmalloc(sizeof(*symbolP));
  232.                     symbolP->sy_nlist.n_un.n_name = "_c$main_args";
  233.                     symbolP->sy_nlist.n_type = N_UNDF;
  234.                     symbolP->sy_nlist.n_other = 0;
  235.                     symbolP->sy_nlist.n_desc = 0;
  236.                     symbolP->sy_nlist.n_value = 0;
  237.                     symbolP->sy_name_offset = 0;
  238.                     symbolP->sy_number = 0;
  239.                     symbolP->sy_frag = New_Frag;
  240.                     symbolP->sy_forward = 0;
  241.                     symbolP->sy_next = symbol_rootP;
  242.                     symbol_rootP = symbolP;
  243.                     /*
  244.                      *    Generate a text fixup structure
  245.                      *    to get "_c$main_args" stored into the
  246.                      *    JSB instruction.
  247.                      */
  248.                     fixP = (struct fix *)xmalloc(sizeof(*fixP));
  249.                     fixP->fx_frag = New_Frag;
  250.                     fixP->fx_where = 4;
  251.                     fixP->fx_addsy = symbolP;
  252.                     fixP->fx_subsy = 0;
  253.                     fixP->fx_offset = 0;
  254.                     fixP->fx_size = sizeof(long);
  255.                     fixP->fx_pcrel = 1;
  256.                     fixP->fx_next = text_fix_root;
  257.                     text_fix_root = fixP;
  258.                     /*
  259.                      *    Now make sure we exit from the loop
  260.                      */
  261.                     frchainP = 0;
  262.                     break;
  263.                 }
  264.                 /*
  265.                  *    Try the next fragment
  266.                  */
  267.                 prev_fragPP = &fragP->fr_next;
  268.                 fragP = fragP->fr_next;
  269.             }
  270.             /*
  271.              *    Try the next fragment chain
  272.              */
  273.             if (frchainP) frchainP=frchainP->frch_next;
  274.         }
  275.     }
  276. #endif    /* HACK_DEC_C_STARTUP */
  277.   }
  278. }
  279.  
  280. /*
  281.  *    Write a VAX/VMS object file (everything else has been done!)
  282.  */
  283. VMS_write_object_file(text_siz, data_siz, text_frag_root, data_frag_root)
  284. unsigned text_siz;
  285. unsigned data_siz;
  286. struct frag *text_frag_root;
  287. struct frag *data_frag_root;
  288. {
  289.    register fragS *        fragP;
  290.    register symbolS *        symbolP;
  291.    register symbolS *        sp;
  292.    register struct fix *    fixP;
  293.    register struct VMS_Symbol *    vsp;
  294.    int Local_Initialized_Data_Size = 0;
  295.    int Psect_Number = 0;        /* Psect Index Number */
  296.    int Text_Psect = -1;            /* Text Psect Index   */
  297.    int Data_Psect = -2;            /* Data Psect Index   JF: Was -1 */
  298.    int Bss_Psect = -3;            /* Bss Psect Index    JF: Was -1 */
  299.  
  300.    /*
  301.     *    Create the VMS object file
  302.     */
  303.    Create_VMS_Object_File();
  304.    /*
  305.     *    Write the module header records
  306.     */
  307.    Write_VMS_MHD_Records();
  308.  
  309.     /*
  310.      *    Generate the VMS object file records
  311.      *    1st GSD then TIR records
  312.      */
  313.  
  314.     /*******       Global Symbol Dictionary       *******/
  315.     /*
  316.      *    Define the Text Psect
  317.      */
  318.     if (text_siz > 0) {
  319.         Text_Psect = Psect_Number++;
  320.         VMS_Psect_Spec("$code",text_siz,"TEXT");
  321.     }
  322.     /*
  323.      *    Define the BSS Psect
  324.      */
  325.     if (local_bss_counter > 0) {
  326.         Bss_Psect = Psect_Number++;
  327.         VMS_Psect_Spec("$uninitialized_data",local_bss_counter,"DATA");
  328.     }
  329.     /*
  330.      *    Now scan the symbols and emit the appropriate GSD records
  331.      */
  332.     for (sp = symbol_rootP; sp; sp = sp->sy_next) {
  333.         /*
  334.          *    Dispatch on symbol type
  335.          */
  336.         switch(sp->sy_type) {
  337.             /*
  338.              *    Global uninitialized data
  339.              */
  340.             case N_UNDF | N_EXT:
  341.                 /*
  342.                  *    Make a VMS data symbol entry
  343.                  */
  344.                 vsp = (struct VMS_Symbol *)
  345.                     xmalloc(sizeof(*vsp));
  346.                 vsp->Symbol = sp;
  347.                 vsp->Size = sp->sy_nlist.n_value;
  348.                 vsp->Psect_Index = Psect_Number++;
  349.                 vsp->Psect_Offset = 0;
  350.                 vsp->Next = VMS_Symbols;
  351.                 VMS_Symbols = vsp;
  352.                 sp->sy_number = (int)vsp;
  353.                 /*
  354.                  *    Make the psect for this data
  355.                  */
  356.                 if(sp->sy_nlist.n_other)
  357.                     VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
  358.                            vsp->Size,
  359.                            "CONST");
  360.                 else
  361.                     VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
  362.                            vsp->Size,
  363.                            "COMMON");
  364. #ifdef    NOT_VAX_11_C_COMPATIBLE
  365.                 /*
  366.                  *    Place a global symbol at the
  367.                  *    beginning of the Psect
  368.                  */
  369.                 VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
  370.                                vsp->Psect_Index,
  371.                                0,
  372.                                1);
  373. #endif    NOT_VAX_11_C_COMPATIBLE
  374.                 break;
  375.             /*
  376.              *    Local uninitialized data
  377.              */
  378.             case N_BSS:
  379.                 /*
  380.                  *    Make a VMS data symbol entry
  381.                  */
  382.                 vsp = (struct VMS_Symbol *)
  383.                     xmalloc(sizeof(*vsp));
  384.                 vsp->Symbol = sp;
  385.                 vsp->Size = 0;
  386.                 vsp->Psect_Index = Bss_Psect;
  387.                 vsp->Psect_Offset =
  388.                     sp->sy_nlist.n_value -
  389.                         bss_address_frag . fr_address;
  390.                 vsp->Next = VMS_Symbols;
  391.                 VMS_Symbols = vsp;
  392.                 sp->sy_number = (int)vsp;
  393.                 break;
  394.             /*
  395.              *    Global initialized data
  396.              */
  397.             case N_DATA | N_EXT:
  398.                 /*
  399.                  *    Make a VMS data symbol entry
  400.                  */
  401.                 vsp = (struct VMS_Symbol *)
  402.                     xmalloc(sizeof(*vsp));
  403.                 vsp->Symbol = sp;
  404.                 vsp->Size = VMS_Initialized_Data_Size(sp,
  405.                             text_siz + data_siz);
  406.                 vsp->Psect_Index = Psect_Number++;
  407.                 vsp->Psect_Offset = 0;
  408.                 vsp->Next = VMS_Symbols;
  409.                 VMS_Symbols = vsp;
  410.                 sp->sy_number = (int)vsp;
  411.                 /*
  412.                  *    Make its psect
  413.                  */
  414.                 if(sp->sy_nlist.n_other)
  415.                     VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
  416.                            vsp->Size,
  417.                            "CONST");
  418.                 else
  419.                     VMS_Psect_Spec(sp->sy_nlist.n_un.n_name,
  420.                            vsp->Size,
  421.                            "COMMON");
  422. #ifdef    NOT_VAX_11_C_COMPATIBLE
  423.                 /*
  424.                  *    Place a global symbol at the
  425.                  *    beginning of the Psect
  426.                  */
  427.                 VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
  428.                                vsp->Psect_Index,
  429.                                0,
  430.                                1);
  431. #endif    NOT_VAX_11_C_COMPATIBLE
  432.                 break;
  433.             /*
  434.              *    Local initialized data
  435.              */
  436.             case N_DATA:
  437.                 /*
  438.                  *    Make a VMS data symbol entry
  439.                  */
  440.                 vsp = (struct VMS_Symbol *)
  441.                     xmalloc(sizeof(*vsp));
  442.                 vsp->Symbol = sp;
  443.                 vsp->Size = 
  444.                     VMS_Initialized_Data_Size(sp,
  445.                               text_siz + data_siz);
  446.                 vsp->Psect_Index = Data_Psect;
  447.                 vsp->Psect_Offset =
  448.                     Local_Initialized_Data_Size;
  449.                 Local_Initialized_Data_Size += vsp->Size;
  450.                 vsp->Next = VMS_Symbols;
  451.                 VMS_Symbols = vsp;
  452.                 sp->sy_number = (int)vsp;
  453.                 break;
  454.             /*
  455.              *    Global Text definition
  456.              */
  457.             case N_TEXT | N_EXT: {
  458.                 unsigned short Entry_Mask;
  459.  
  460.                 /*
  461.                  *    Get the entry mask
  462.                  */
  463.                 fragP = sp->sy_frag;
  464.                 Entry_Mask = (fragP->fr_literal[0] & 0xff) +
  465.                         ((fragP->fr_literal[1] & 0xff)
  466.                             << 8);
  467.                 /*
  468.                  *    Define the Procedure entry pt.
  469.                  */
  470.                 VMS_Procedure_Entry_Pt(sp->sy_nlist.n_un.n_name,
  471.                                Text_Psect,
  472.                                sp->sy_nlist.n_value,
  473.                                Entry_Mask);
  474.                 break;
  475.             }
  476.             /*
  477.              *    Local Text definition
  478.              */
  479.             case N_TEXT:
  480.                 /*
  481.                  *    Make a VMS data symbol entry
  482.                  */
  483.                  if(Text_Psect != -1) {
  484.                     vsp = (struct VMS_Symbol *)
  485.                         xmalloc(sizeof(*vsp));
  486.                     vsp->Symbol = sp;
  487.                     vsp->Size = 0;
  488.                     vsp->Psect_Index = Text_Psect;
  489.                     vsp->Psect_Offset = sp->sy_nlist.n_value;
  490.                     vsp->Next = VMS_Symbols;
  491.                     VMS_Symbols = vsp;
  492.                     sp->sy_number = (int)vsp;
  493.                  }
  494.                 break;
  495.             /*
  496.              *    Global Reference
  497.              */
  498.             case N_UNDF:
  499.                 /*
  500.                  *    Make a GSD global symbol reference
  501.                  *    record.
  502.                  */
  503.                 VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
  504.                                0,
  505.                                0,
  506.                                0);
  507.                 break;
  508.             /*
  509.              *    Anything else
  510.              */
  511.             default:
  512.                 /*
  513.                  *    Ignore STAB symbols
  514.                  *    Including .stabs emitted by g++
  515.                  */
  516.                 if ((sp->sy_type & N_STAB) != 0 || sp->sy_nlist.n_type==22)
  517.                     break;
  518.                 /*
  519.                  *    Error
  520.                  */
  521.                 if(sp->sy_nlist.n_type !=22)
  522.                     printf(" ERROR, unknown type (%d)\n",
  523.                         sp->sy_nlist.n_type);
  524.                 break;
  525.         }
  526.     }
  527.     /*
  528.      *    Define the Data Psect
  529.      */
  530.     if ((data_siz > 0) && (Local_Initialized_Data_Size > 0)) {
  531.         /*
  532.          *    Do it
  533.          */
  534.         Data_Psect = Psect_Number++;
  535.         VMS_Psect_Spec("$data",
  536.                 Local_Initialized_Data_Size,
  537.                 "DATA");
  538.         /*
  539.          *    Scan the VMS symbols and fill in the data psect
  540.          */
  541.         for (vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
  542.             /*
  543.              *    Only look for undefined psects
  544.              */
  545.             if (vsp->Psect_Index < 0)  {
  546.                 /*
  547.                  *    And only initialized data
  548.                  */
  549.                 if (vsp->Symbol->sy_nlist.n_type == N_DATA)
  550.                     vsp->Psect_Index = Data_Psect;
  551.             }
  552.         }
  553.     }
  554.  
  555.     /*******  Text Information and Relocation Records  *******/
  556.     /*
  557.      *    Write the text segment data
  558.      */
  559.     if (text_siz > 0) {
  560.         /*
  561.          *    Scan the text fragments
  562.          */
  563.         for(fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
  564.             /*
  565.              *    Stop if we get to the data fragments
  566.              */
  567.             if (fragP == data_frag_root) break;
  568.             /*
  569.              *    Ignore fragments with no data
  570.              */
  571.             if ((fragP->fr_fix == 0) && (fragP->fr_var == 0))
  572.                 continue;
  573.             /*
  574.              *    Go the the appropriate offset in the
  575.              *    Text Psect.
  576.              */
  577.             VMS_Set_Psect(Text_Psect,fragP->fr_address,OBJ$C_TIR);
  578.             /*
  579.              *    Store the "fixed" part
  580.              */
  581.             if (fragP->fr_fix)
  582.                 VMS_Store_Immediate_Data(fragP->fr_literal,
  583.                              fragP->fr_fix,
  584.                              OBJ$C_TIR);
  585.             /*
  586.              *    Store the "variable" part
  587.              */
  588.             if (fragP->fr_var && fragP->fr_offset)
  589.                 VMS_Store_Repeated_Data(fragP->fr_offset,
  590.                             fragP->fr_literal+
  591.                                  fragP->fr_fix,
  592.                             fragP->fr_var,
  593.                             OBJ$C_TIR);
  594.         }
  595.         /*
  596.          *    Now we go through the text segment fixups and
  597.          *    generate TIR records to fix up addresses within
  598.          *    the Text Psect
  599.          */
  600.         for(fixP = text_fix_root; fixP; fixP = fixP->fx_next) {
  601.             /*
  602.              *    We DO handle the case of "Symbol - Symbol" as
  603.              *    long as it is in the same segment.
  604.              */
  605.             if (fixP->fx_subsy && fixP->fx_addsy) {
  606.                 int i;
  607.  
  608.                 /*
  609.                  *    They need to be in the same segment
  610.                  */
  611.                 if (fixP->fx_subsy->sy_type !=
  612.                             fixP->fx_addsy->sy_type)
  613.                     error("Fixup data addsy and subsy didn't have the same type");
  614.                 /*
  615.                  *    And they need to be in one that we
  616.                  *    can check the psect on
  617.                  */
  618.                 if (((fixP->fx_addsy->sy_type & ~N_EXT) != N_DATA) &&
  619.                     ((fixP->fx_addsy->sy_type & ~N_EXT) != N_TEXT))
  620.                     error("Fixup data addsy and subsy didn't have an appropriate type");
  621.                 /*
  622.                  *    This had better not be PC relative!
  623.                  */
  624.                 if (fixP->fx_pcrel)
  625.                     error("Fixup data was erroneously \"pcrel\"");
  626.                 /*
  627.                  *    Subtract their values to get the
  628.                  *    difference.
  629.                  */
  630.                 i = fixP->fx_addsy->sy_value -
  631.                         fixP->fx_subsy->sy_value;
  632.                 /*
  633.                  *    Now generate the fixup object records
  634.                  *    Set the psect and store the data
  635.                  */
  636.                 VMS_Set_Psect(Text_Psect,
  637.                           fixP->fx_where +
  638.                              fixP->fx_frag->fr_address,
  639.                           OBJ$C_TIR);
  640.                 VMS_Store_Immediate_Data(&i,
  641.                              fixP->fx_size,
  642.                              OBJ$C_TIR);
  643.                 /*
  644.                  *    Done
  645.                  */
  646.                 continue;
  647.             }
  648.             /*
  649.              *    Size will HAVE to be "long"
  650.              */
  651.             if (fixP->fx_size != sizeof(long))
  652.                 error("Fixup datum was not a longword");
  653.             /*
  654.              *    Symbol must be "added" (if it is ever
  655.              *                subtracted we can
  656.              *                fix this assumption)
  657.              */
  658.             if (fixP->fx_addsy == 0)
  659.                 error("Fixup datum was not \"fixP->fx_addsy\"");
  660.             /*
  661.              *    Store the symbol value in a PIC fashion
  662.              */
  663.             VMS_Store_PIC_Symbol_Reference(fixP->fx_addsy,
  664.                                fixP->fx_offset,
  665.                                fixP->fx_pcrel,
  666.                                Text_Psect,
  667.                                fixP->fx_where +
  668.                                   fixP->fx_frag->fr_address,
  669.                                OBJ$C_TIR);
  670.             /*
  671.              *    Check for indirect address reference,
  672.              *    which has to be fixed up (as the linker
  673.              *    will screw it up with TIR$C_STO_PICR).
  674.              */
  675.             if (fixP->fx_pcrel)
  676.                 VMS_Fix_Indirect_Reference(Text_Psect,
  677.                                fixP->fx_where +
  678.                                 fixP->fx_frag->fr_address,
  679.                                fixP->fx_frag,
  680.                                text_frag_root);
  681.         }
  682.     }
  683.     /*
  684.      *    Store the Data segment:
  685.      *
  686.      *    Since this is REALLY hard to do any other way,
  687.      *    we actually manufacture the data segment and
  688.      *    the store the appropriate values out of it.
  689.      */
  690.     if (data_siz > 0) {
  691.         char *Data_Segment;
  692.  
  693.         /*
  694.          *    Allocate the data segment
  695.          */
  696.         Data_Segment = (char *)xmalloc(data_siz);
  697.         /*
  698.          *    Run through the data fragments, filling in the segment
  699.          */
  700.         for(fragP = data_frag_root; fragP; fragP = fragP->fr_next) {
  701.             register long int        count;
  702.             register char     *        fill_literal;
  703.             register long int        fill_size;
  704.             int i;
  705.  
  706.             i = fragP->fr_address - text_siz;
  707.             if (fragP->fr_fix)
  708.                 bcopy(fragP->fr_literal,
  709.                       Data_Segment + i,
  710.                       fragP->fr_fix);
  711.             i += fragP->fr_fix;
  712.  
  713.             fill_literal= fragP -> fr_literal + fragP -> fr_fix;
  714.             fill_size   = fragP -> fr_var;
  715.             for (count = fragP -> fr_offset;  count;  count --) {
  716.                 if (fill_size)
  717.                     bcopy(fill_literal,
  718.                           Data_Segment + i,
  719.                           fill_size);
  720.                 i += fill_size;
  721.             }
  722.         }
  723.         /*
  724.          *    Now we can run through all the data symbols
  725.          *    and store the data
  726.          */
  727.         for(vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
  728.             /*
  729.              *    Ignore anything other than data symbols
  730.              */
  731.             if ((vsp->Symbol->sy_nlist.n_type & ~N_EXT) != N_DATA)
  732.                 continue;
  733.             /*
  734.              *    Set the Psect + Offset
  735.              */
  736.             VMS_Set_Psect(vsp->Psect_Index,
  737.                       vsp->Psect_Offset,
  738.                       OBJ$C_TIR);
  739.             /*
  740.              *    Store the data
  741.              */
  742.             VMS_Store_Immediate_Data(Data_Segment +
  743.                             vsp->Symbol->sy_nlist.n_value -
  744.                                 text_siz,
  745.                          vsp->Size,
  746.                          OBJ$C_TIR);
  747.         }
  748.         /*
  749.          *    Now we go through the data segment fixups and
  750.          *    generate TIR records to fix up addresses within
  751.          *    the Data Psects
  752.          */
  753.         for(fixP = data_fix_root; fixP; fixP = fixP->fx_next) {
  754.             /*
  755.              *    Find the symbol for the containing datum
  756.              */
  757.             for(vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
  758.                 /*
  759.                  *    Only bother with Data symbols
  760.                  */
  761.                 sp = vsp->Symbol;
  762.                 if ((sp->sy_nlist.n_type & ~N_EXT) != N_DATA)
  763.                     continue;
  764.                 /*
  765.                  *    Ignore symbol if After fixup
  766.                  */
  767.                 if (sp->sy_nlist.n_value >
  768.                     (fixP->fx_where +
  769.                         fixP->fx_frag->fr_address))
  770.                     continue;
  771.                 /*
  772.                  *    See if the datum is here
  773.                  */
  774.                 if ((sp->sy_nlist.n_value + vsp->Size) <=
  775.                     (fixP->fx_where +
  776.                         fixP->fx_frag->fr_address))
  777.                     continue;
  778.                 /*
  779.                  *    We DO handle the case of "Symbol - Symbol" as
  780.                  *    long as it is in the same segment.
  781.                  */
  782.                 if (fixP->fx_subsy && fixP->fx_addsy) {
  783.                     int i;
  784.  
  785.                     /*
  786.                      *    They need to be in the same segment
  787.                      */
  788.                     if (fixP->fx_subsy->sy_type !=
  789.                                 fixP->fx_addsy->sy_type)
  790.                         error("Fixup data addsy and subsy didn't have the same type");
  791.                     /*
  792.                      *    And they need to be in one that we
  793.                      *    can check the psect on
  794.                      */
  795.                     if (((fixP->fx_addsy->sy_type & ~N_EXT) != N_DATA) &&
  796.                         ((fixP->fx_addsy->sy_type & ~N_EXT) != N_TEXT))
  797.                         error("Fixup data addsy and subsy didn't have an appropriate type");
  798.                     /*
  799.                      *    This had better not be PC relative!
  800.                      */
  801.                     if (fixP->fx_pcrel)
  802.                         error("Fixup data was erroneously \"pcrel\"");
  803.                     /*
  804.                      *    Subtract their values to get the
  805.                      *    difference.
  806.                      */
  807.                     i = fixP->fx_addsy->sy_value -
  808.                             fixP->fx_subsy->sy_value;
  809.                     /*
  810.                      *    Now generate the fixup object records
  811.                      *    Set the psect and store the data
  812.                      */
  813.                     VMS_Set_Psect(vsp->Psect_Index,
  814.                               fixP->fx_frag->fr_address +
  815.                                 fixP->fx_where -
  816.                               vsp->Symbol->sy_value +
  817.                                 vsp->Psect_Offset,
  818.                               OBJ$C_TIR);
  819.                     VMS_Store_Immediate_Data(&i,
  820.                                  fixP->fx_size,
  821.                                  OBJ$C_TIR);
  822.                     /*
  823.                      *    Done
  824.                      */
  825.                     break;
  826.                 }
  827.                 /*
  828.                  *    Size will HAVE to be "long"
  829.                  */
  830.                 if (fixP->fx_size != sizeof(long))
  831.                     error("Fixup datum was not a longword");
  832.                 /*
  833.                  *    Symbol must be "added" (if it is ever
  834.                  *                subtracted we can
  835.                  *                fix this assumption)
  836.                  */
  837.                 if (fixP->fx_addsy == 0)
  838.                     error("Fixup datum was not \"fixP->fx_addsy\"");
  839.                 /*
  840.                  *    Store the symbol value in a PIC fashion
  841.                  */
  842.                 VMS_Store_PIC_Symbol_Reference(
  843.                     fixP->fx_addsy,
  844.                     fixP->fx_offset,
  845.                     fixP->fx_pcrel,
  846.                     vsp->Psect_Index,
  847.                     fixP->fx_frag->fr_address +
  848.                         fixP->fx_where -
  849.                           vsp->Symbol->sy_value +
  850.                              vsp->Psect_Offset,
  851.                     OBJ$C_TIR);
  852.                 /*
  853.                  *    Done
  854.                  */
  855.                 break;
  856.             }
  857.             
  858.         }
  859.     }
  860.  
  861.     /*
  862.      *    Write the Traceback Begin Module record
  863.      */
  864.     VMS_TBT_Module_Begin();
  865.     /*
  866.      *    Scan the symbols and write out the routines
  867.      *    (this makes the assumption that symbols are in
  868.      *     order of ascending text segment offset)
  869.      */
  870.     {
  871.        struct symbol *Current_Routine = 0;
  872.        int Current_Line_Number = 0;
  873.        int Current_Offset = -1;
  874.        struct input_file * Current_File;
  875.  
  876. /* Output debugging info for global variables and static variables that are not
  877.  * specific to one routine. We also need to examine all stabs directives, to
  878.  * find the definitions to all of the advanced data types, and this is done by
  879.  * VMS_LSYM_Parse.  This needs to be done before any definitions are output to
  880.  * the object file, since there can be forward references in the stabs
  881.  * directives. When through with parsing, the text of the stabs directive
  882.  * is altered, with the definitions removed, so that later passes will see
  883.  * directives as they would be written if the type were already defined.
  884.  *
  885.  * We also look for files and include files, and make a list of them.  We
  886.  * examine the source file numbers to establish the actual lines that code was
  887.  * generated from, and then generate offsets.
  888.  */
  889.     VMS_LSYM_Parse();
  890.        for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next) {
  891.         /*
  892.          *    Deal with STAB symbols
  893.          */
  894.         if ((symbolP->sy_nlist.n_type & N_STAB) != 0) {
  895.           /*
  896.            *    Dispatch on STAB type
  897.            */
  898.           switch((unsigned char)symbolP->sy_nlist.n_type) {
  899.             case N_SLINE:
  900.             if(symbolP->sy_nlist.n_desc > Current_File->max_line)
  901.                Current_File->max_line = symbolP->sy_nlist.n_desc;
  902.             if(symbolP->sy_nlist.n_desc < Current_File->min_line)
  903.                Current_File->min_line = symbolP->sy_nlist.n_desc;
  904.             break;            
  905.             case N_SO:
  906.             Current_File =find_file(symbolP);
  907.             Current_File->flag = 1;
  908.             Current_File->min_line = 1;
  909.                 break;
  910.             case N_SOL:
  911.             Current_File = find_file(symbolP);
  912.                 break;
  913.             case N_GSYM:
  914.                 VMS_GSYM_Parse(symbolP,Text_Psect);
  915.                 break;
  916.             case N_LCSYM:
  917.                 VMS_LCSYM_Parse(symbolP,Text_Psect);
  918.                 break;
  919.             case N_FUN:        /* For static constant symbols */
  920.             case N_STSYM:
  921.                 VMS_STSYM_Parse(symbolP,Text_Psect);
  922.                 break;
  923.           }
  924.         }
  925.        }
  926.  
  927.     /* now we take a quick sweep through the files and assign offsets
  928.     to each one.  This will essentially be the starting line number to the
  929.        debugger for each file.  Output the info for the debugger to specify the
  930.        files, and then tell it how many lines to use */
  931.     {
  932.     int File_Number = 0;
  933.     int Debugger_Offset = 0;
  934.     int file_available;
  935.     Current_File = file_root;
  936.     for(Current_File = file_root; Current_File; Current_File = Current_File->next){
  937.       if(Current_File == (struct input_file*) NULL) break;
  938.       if(Current_File->max_line == 0) continue;
  939.       if((strncmp(Current_File->name,"GNU_GXX_INCLUDE:",16) == 0) &&
  940.         !flagseen['D']) continue;
  941.       if((strncmp(Current_File->name,"GNU_CC_INCLUDE:",15) == 0) &&
  942.         !flagseen['D']) continue;
  943. /* show a few extra lines at the start of the region selected */
  944.       if(Current_File->min_line > 2) Current_File->min_line -= 2;
  945.       Current_File->offset = Debugger_Offset - Current_File->min_line + 1;
  946.       Debugger_Offset += Current_File->max_line - Current_File->min_line + 1;
  947.       if(Current_File->same_file_fpnt != (struct input_file *) NULL)
  948.        Current_File->file_number =Current_File->same_file_fpnt->file_number;
  949.       else {
  950.         Current_File->file_number = ++File_Number;
  951.         file_available = VMS_TBT_Source_File(Current_File->name,
  952.         Current_File->file_number);
  953.         if(!file_available) {Current_File->file_number = 0;
  954.                 File_Number--;
  955.                 continue;};
  956.       };
  957.       VMS_TBT_Source_Lines(Current_File->file_number,
  958.             Current_File->min_line,
  959.             Current_File->max_line-Current_File->min_line+1);
  960.       }; /* for */
  961.     };    /* scope */
  962.     Current_File = (struct input_file*) NULL;
  963.  
  964.        for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next) {
  965.         /*
  966.          *    Deal with text symbols
  967.          */
  968.         if ((symbolP->sy_nlist.n_type & ~N_EXT) == N_TEXT) {
  969.             /*
  970.              *    Ignore symbols starting with "L",
  971.              *    as they are local symbols
  972.              */
  973.             if (symbolP->sy_nlist.n_un.n_name[0] == 'L') continue;
  974.             /*
  975.              *    If there is a routine start defined,
  976.              *    terminate it.
  977.              */
  978.             if (Current_Routine) {
  979.                 /*
  980.                  *    End the routine
  981.                  */
  982.                 VMS_TBT_Routine_End(text_siz,Current_Routine);
  983.             }
  984.             /*
  985.              *    Store the routine begin traceback info
  986.              */
  987.             if(Text_Psect != -1) {
  988.                 VMS_TBT_Routine_Begin(symbolP,Text_Psect);
  989.                 Current_Routine = symbolP;
  990.             }
  991. /* Output local symbols, i.e. all symbols that are associated with a specific
  992.  * routine.  We output them now so the debugger recognizes them as local to
  993.  * this routine.
  994.  */
  995.     { symbolS * symbolP1;
  996.       char* pnt;
  997.       char* pnt1;
  998.        for(symbolP1 = Current_Routine; symbolP1; symbolP1 = symbolP1->sy_next) {
  999.         if ((symbolP1->sy_nlist.n_type & N_STAB) == 0) continue;
  1000.         if (symbolP1->sy_nlist.n_type != N_FUN) continue;
  1001.         pnt=symbolP->sy_nlist.n_un.n_name;
  1002.         pnt1=symbolP1->sy_nlist.n_un.n_name;
  1003.         if(*pnt++ != '_') continue;
  1004.         while(*pnt++ == *pnt1++) {};
  1005.         if((*(--pnt) == '\0') && (*(--pnt1) == ':')) break;
  1006.         };
  1007.       if(symbolP1 != (symbolS *) NULL)
  1008.         VMS_DBG_Define_Routine(symbolP1,Current_Routine,Text_Psect);
  1009.     } /* local symbol block */
  1010.             /*
  1011.              *    Done
  1012.              */
  1013.             continue;
  1014.         }
  1015.         /*
  1016.          *    Deal with STAB symbols
  1017.          */
  1018.         if ((symbolP->sy_nlist.n_type & N_STAB) != 0) {
  1019.           /*
  1020.            *    Dispatch on STAB type
  1021.            */
  1022.           switch((unsigned char)symbolP->sy_nlist.n_type) {
  1023.             /*
  1024.              *    Line number
  1025.              */
  1026.             case N_SLINE:
  1027.                 /* Offset the line into the correct portion
  1028.                  * of the file */
  1029.                 if(Current_File->file_number == 0) break;
  1030.                 /* Sometimes the same offset gets several source
  1031.                  * lines assigned to it.
  1032.                  * We should be selective about which lines
  1033.                  * we allow, we should prefer lines that are
  1034.                  * in the main source file when debugging
  1035.                  * inline functions. */
  1036.                 if((Current_File->file_number != 1) &&
  1037.                     symbolP->sy_nlist.n_value == 
  1038.                     Current_Offset) break;
  1039.                 /* calculate actual debugger source line */
  1040.                 symbolP->sy_nlist.n_desc 
  1041.                     += Current_File->offset;
  1042.                 /*
  1043.                  *    If this is the 1st N_SLINE, setup
  1044.                  *    PC/Line correlation.  Otherwise
  1045.                  *    do the delta PC/Line.  If the offset
  1046.                  *    for the line number is not +ve we need
  1047.                  *    to do another PC/Line correlation
  1048.                  *    setup
  1049.                  */
  1050.                 if (Current_Offset == -1) {
  1051.                    VMS_TBT_Line_PC_Correlation(
  1052.                         symbolP->sy_nlist.n_desc,
  1053.                         symbolP->sy_nlist.n_value,
  1054.                         Text_Psect,
  1055.                         0);
  1056.                 } else {
  1057.                    if ((symbolP->sy_nlist.n_desc -
  1058.                         Current_Line_Number) <= 0) {
  1059.                     /*
  1060.                      *    Line delta is not +ve, we
  1061.                      *    need to close the line and
  1062.                      *    start a new PC/Line
  1063.                      *    correlation.
  1064.                      */
  1065.                     VMS_TBT_Line_PC_Correlation(0,
  1066.                         symbolP->sy_nlist.n_value -
  1067.                             Current_Offset,
  1068.                         0,
  1069.                         -1);
  1070.                     VMS_TBT_Line_PC_Correlation(
  1071.                         symbolP->sy_nlist.n_desc,
  1072.                         symbolP->sy_nlist.n_value,
  1073.                         Text_Psect,
  1074.                         0);
  1075.                    } else {
  1076.                     /*
  1077.                      *    Line delta is +ve, all is well
  1078.                      */
  1079.                     VMS_TBT_Line_PC_Correlation(
  1080.                         symbolP->sy_nlist.n_desc -
  1081.                             Current_Line_Number,
  1082.                         symbolP->sy_nlist.n_value -
  1083.                             Current_Offset,
  1084.                         0,
  1085.                         1);
  1086.                    }
  1087.                 }
  1088.                 /*
  1089.                  *    Update the current line/PC
  1090.                  */
  1091.                 Current_Line_Number = symbolP->sy_nlist.n_desc;
  1092.                 Current_Offset = symbolP->sy_nlist.n_value;
  1093.                 /*
  1094.                  *    Done
  1095.                  */
  1096.                 break;
  1097.             /*
  1098.              *    Source file
  1099.              */
  1100.             case N_SO:
  1101.                 /*
  1102.                  *    Remember that we had a source file
  1103.                  *    and emit the source file debugger
  1104.                  *    record
  1105.                  */
  1106.                 Current_File =
  1107.                     find_file(symbolP);
  1108.                 break;
  1109. /* We need to make sure that we are really in the actual source file when
  1110.  * we compute the maximum line number.  Otherwise the debugger gets really
  1111.  * confused */
  1112.             case N_SOL:
  1113.                 Current_File =
  1114.                     find_file(symbolP);
  1115.                 break;
  1116.           }
  1117.         }
  1118.        }
  1119.        /*
  1120.         *    If there is a routine start defined,
  1121.         *    terminate it (and the line numbers)
  1122.         */
  1123.        if (Current_Routine) {
  1124.         /*
  1125.          *    Terminate the line numbers
  1126.          */
  1127.         VMS_TBT_Line_PC_Correlation(0,
  1128.                         text_siz - Current_Routine->sy_nlist.n_value,
  1129.                         0,
  1130.                         -1);
  1131.         /*
  1132.          *    Terminate the routine
  1133.          */
  1134.         VMS_TBT_Routine_End(text_siz,Current_Routine);
  1135.        }
  1136.     }
  1137.     /*
  1138.      *    Write the Traceback End Module TBT record
  1139.      */
  1140.     VMS_TBT_Module_End();
  1141.  
  1142.     /*
  1143.      *    Write the End Of Module record
  1144.      */
  1145.     if (Entry_Point_Symbol == 0)
  1146.         Write_VMS_EOM_Record(-1,0);
  1147.     else
  1148.         Write_VMS_EOM_Record(Text_Psect,
  1149.                      Entry_Point_Symbol->sy_nlist.n_value);
  1150.  
  1151.    /*
  1152.     *    All done, close the object file
  1153.     */
  1154.    Close_VMS_Object_File();
  1155. }
  1156.  
  1157.  
  1158.     /****** VMS OBJECT FILE HACKING ROUTINES *******/
  1159.  
  1160.  
  1161. /*
  1162.  *    Global data (Object records limited to 512 bytes by VAX-11 "C" runtime)
  1163.  */
  1164. static int VMS_Object_File_FD;        /* File Descriptor for object file */
  1165. static char Object_Record_Buffer[512];    /* Buffer for object file records  */
  1166. static int Object_Record_Offset;    /* Offset to end of data       */
  1167. static int Current_Object_Record_Type;    /* Type of record in above       */
  1168.  
  1169. /*
  1170.  *    Macros for placing data into the object record buffer
  1171.  */
  1172. #define    PUT_LONG(val)    *((long *)(Object_Record_Buffer + \
  1173.                   Object_Record_Offset)) = val; \
  1174.             Object_Record_Offset += sizeof(long)
  1175.  
  1176. #define    PUT_SHORT(val)    *((short *)(Object_Record_Buffer + \
  1177.                   Object_Record_Offset)) = val; \
  1178.             Object_Record_Offset += sizeof(short)
  1179.  
  1180. #define    PUT_CHAR(val)    Object_Record_Buffer[Object_Record_Offset++] = val
  1181.  
  1182. #define    PUT_COUNTED_STRING(cp) {\
  1183.             register char *p = cp; \
  1184.             PUT_CHAR(strlen(p)); \
  1185.             while(*p) PUT_CHAR(*p++);}
  1186.  
  1187. /*
  1188.  *    Macro for determining if a Name has psect attributes attached
  1189.  *    to it.
  1190.  */
  1191. #define    PSECT_ATTRIBUTES_STRING        "$$PsectAttributes_"
  1192. #define    PSECT_ATTRIBUTES_STRING_LENGTH    18
  1193.  
  1194. #define    HAS_PSECT_ATTRIBUTES(Name) \
  1195.         (strncmp((Name[0] == '_' ? Name + 1 : Name), \
  1196.          PSECT_ATTRIBUTES_STRING, \
  1197.          PSECT_ATTRIBUTES_STRING_LENGTH) == 0)
  1198.  
  1199.  
  1200. /*
  1201.  *    Create the VMS object file
  1202.  */
  1203. Create_VMS_Object_File()
  1204. {
  1205. #ifdef    eunice
  1206.     VMS_Object_File_FD = creat(out_file_name, 0777, "var");
  1207. #else    eunice
  1208.     VMS_Object_File_FD = creat(out_file_name, 0, "rfm=var");
  1209. #endif    eunice
  1210.     /*
  1211.      *    Deal with errors
  1212.      */
  1213.     if (VMS_Object_File_FD < 0) {
  1214.         char Error_Line[256];
  1215.  
  1216.         sprintf(Error_Line,"Couldn't create VMS object file \"%s\"",
  1217.                 out_file_name);
  1218.         error(Error_Line);
  1219.     }
  1220.     /*
  1221.      *    Initialize object file hacking variables
  1222.      */
  1223.     Object_Record_Offset = 0;
  1224.     Current_Object_Record_Type = -1;
  1225. }
  1226.  
  1227.  
  1228. /*
  1229.  *    Declare a particular type of object file record
  1230.  */
  1231. Set_VMS_Object_File_Record(Type)
  1232. int Type;
  1233. {
  1234.     /*
  1235.      *    If the type matches, we are done
  1236.      */
  1237.     if (Type == Current_Object_Record_Type) return;
  1238.     /*
  1239.      *    Otherwise: flush the buffer
  1240.      */
  1241.     Flush_VMS_Object_Record_Buffer();
  1242.     /*
  1243.      *    Set the new type
  1244.      */
  1245.     Current_Object_Record_Type = Type;
  1246. }
  1247.  
  1248.  
  1249. /*
  1250.  *    Flush the object record buffer to the object file
  1251.  */
  1252. Flush_VMS_Object_Record_Buffer()
  1253. {
  1254.     int i;
  1255.  
  1256.     /*
  1257.      *    If the buffer is empty, we are done
  1258.      */
  1259.     if (Object_Record_Offset == 0) return;
  1260.     /*
  1261.      *    Write the data to the file
  1262.      */
  1263.     i= write(VMS_Object_File_FD,
  1264.          Object_Record_Buffer,
  1265.          Object_Record_Offset);
  1266.     if (i != Object_Record_Offset)
  1267.         error("I/O error writing VMS object file");
  1268.     /*
  1269.      *    The buffer is now empty
  1270.      */
  1271.     Object_Record_Offset = 0;
  1272. }
  1273.  
  1274.  
  1275. /*
  1276.  *    Close the VMS Object file
  1277.  */
  1278. Close_VMS_Object_File()
  1279. {
  1280.     close(VMS_Object_File_FD);
  1281. }
  1282.  
  1283.  
  1284. /*
  1285.  *    Write the MHD (Module Header) records
  1286.  */
  1287. Write_VMS_MHD_Records()
  1288. {
  1289.     register char *cp,*cp1;
  1290.     register int i;
  1291.     struct {int Size; char *Ptr;} Descriptor;
  1292.     char Module_Name[256];
  1293.     char Now[17];
  1294.  
  1295.     /*
  1296.      *    We are writing a module header record
  1297.      */
  1298.     Set_VMS_Object_File_Record(OBJ$C_HDR);
  1299.     /*
  1300.      *    ***************************
  1301.      *    *MAIN MODULE HEADER RECORD*
  1302.      *    ***************************
  1303.      *
  1304.      *    Store record type and header type
  1305.      */
  1306.     PUT_CHAR(OBJ$C_HDR);
  1307.     PUT_CHAR(MHD$C_MHD);
  1308.     /*
  1309.      *    Structure level is 0
  1310.      */
  1311.     PUT_CHAR(OBJ$C_STRLVL);
  1312.     /*
  1313.      *    Maximum record size is size of the object record buffer
  1314.      */
  1315.     PUT_SHORT(sizeof(Object_Record_Buffer));
  1316.     /*
  1317.      *    Get module name (the FILENAME part of the object file)
  1318.      */
  1319.     cp = out_file_name;
  1320.     cp1 = Module_Name;
  1321.     while(*cp) {
  1322.         if ((*cp == ']') || (*cp == '>') ||
  1323.             (*cp == ':') || (*cp == '/')) {
  1324.             cp1 = Module_Name;
  1325.             cp++;
  1326.             continue;
  1327.         }
  1328.         *cp1++ = islower(*cp) ? toupper(*cp++) : *cp++;
  1329.     }
  1330.     *cp1 = 0;
  1331.     /*
  1332.      *    Limit it to 31 characters and store in the object record
  1333.      */
  1334.     while(--cp1 >= Module_Name)
  1335.         if (*cp1 == '.') *cp1 = 0;
  1336.     if (strlen(Module_Name) > 31) {
  1337.          if(flagseen['+'])
  1338.             printf("%s: Module name truncated: %s\n", myname, Module_Name);
  1339.         Module_Name[31] = 0;
  1340.     }
  1341.     PUT_COUNTED_STRING(Module_Name);
  1342.     /*
  1343.      *    Module Version is "V1.0"
  1344.      */
  1345.     PUT_COUNTED_STRING("V1.0");
  1346.     /*
  1347.      *    Creation time is "now" (17 chars of time string)
  1348.      */
  1349.     Descriptor.Size = 17;
  1350.     Descriptor.Ptr = Now;
  1351.     sys$asctim(0,&Descriptor,0,0);
  1352.     for(i = 0; i < 17; i++) PUT_CHAR(Now[i]);
  1353.     /*
  1354.      *    Patch time is "never" (17 zeros)
  1355.      */
  1356.     for(i = 0; i < 17; i++) PUT_CHAR(0);
  1357.     /*
  1358.      *    Flush the record
  1359.      */
  1360.     Flush_VMS_Object_Record_Buffer();
  1361.     /*
  1362.      *    *************************
  1363.      *    *LANGUAGE PROCESSOR NAME*
  1364.      *    *************************
  1365.      *
  1366.      *    Store record type and header type
  1367.      */
  1368.     PUT_CHAR(OBJ$C_HDR);
  1369.     PUT_CHAR(MHD$C_LNM);
  1370.     /*
  1371.      *    Store language processor name and version
  1372.      *    (not a counted string!)
  1373.      */
  1374.     cp = compiler_version_string;
  1375.     if (cp == 0) {
  1376.         cp ="GNU AS  V";
  1377.         while(*cp) PUT_CHAR(*cp++);
  1378.         cp = strchr(&version_string,'.');        
  1379.         while(*cp != ' ') cp--; cp++;
  1380.         };
  1381.     while(*cp >= 32) PUT_CHAR(*cp++);
  1382.     /*
  1383.      *    Flush the record
  1384.      */
  1385.     Flush_VMS_Object_Record_Buffer();
  1386. }
  1387.  
  1388.  
  1389. /*
  1390.  *    Write the EOM (End Of Module) record
  1391.  */
  1392. Write_VMS_EOM_Record(Psect, Offset)
  1393. int Psect;
  1394. int Offset;
  1395. {
  1396.     /*
  1397.      *    We are writing an end-of-module record
  1398.      */
  1399.     Set_VMS_Object_File_Record(OBJ$C_EOM);
  1400.     /*
  1401.      *    Store record Type
  1402.      */
  1403.     PUT_CHAR(OBJ$C_EOM);
  1404.     /*
  1405.      *    Store the error severity (0)
  1406.      */
  1407.     PUT_CHAR(0);
  1408.     /*
  1409.      *    Store the entry point, if it exists
  1410.      */
  1411.     if (Psect >= 0) {
  1412.         /*
  1413.          *    Store the entry point Psect
  1414.          */
  1415.         PUT_CHAR(Psect);
  1416.         /*
  1417.          *    Store the entry point Psect offset
  1418.          */
  1419.         PUT_LONG(Offset);
  1420.     }
  1421.     /*
  1422.      *    Flush the record
  1423.      */
  1424.     Flush_VMS_Object_Record_Buffer();
  1425. }
  1426.  
  1427.  
  1428. /* this hash routine borrowed from GNU-EMACS, and strengthened slightly  ERY*/
  1429.  
  1430. static int
  1431. hash_string (ptr)
  1432.      unsigned char *ptr;
  1433. {
  1434.   register unsigned char *p = ptr;
  1435.   register unsigned char *end = p + strlen(ptr);
  1436.   register unsigned char c;
  1437.   register int hash = 0;
  1438.  
  1439.   while (p != end)
  1440.     {
  1441.       c = *p++;
  1442.       hash = ((hash<<3) + (hash<<15) + (hash>>28) + c);
  1443.     }
  1444.   return hash;
  1445. }
  1446.  
  1447. /*
  1448.  *    Generate a Case-Hacked VMS symbol name (limited to 31 chars)
  1449.  */
  1450. VMS_Case_Hack_Symbol(In,Out)
  1451. register char *In;
  1452. register char *Out;
  1453. {
  1454.     long int init = 0;
  1455.     long int result;
  1456.     char *pnt;
  1457.     char *new_name;
  1458.     char *old_name;
  1459.     register int i;
  1460.     int destructor = 0;    /*hack to allow for case sens in a destructor*/
  1461.     int truncate = 0;
  1462.     int Case_Hack_Bits = 0;
  1463.     int Saw_Dollar = 0;
  1464.     static char Hex_Table[16] =
  1465.      {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
  1466.  
  1467.     /*
  1468.      *    Kill any leading "_"
  1469.      */
  1470.     if (*In == '_') In++;
  1471.  
  1472.     new_name=Out;    /* save this for later*/
  1473.  
  1474.     if((In[0]=='_')&&(In[1]=='$')&&(In[2]=='_'))
  1475.                          destructor=1;
  1476.  
  1477.     /* We may need to truncate the symbol, save the hash for later*/
  1478.     if(strlen(In)>23)  result = hash_string(In);
  1479.     /*
  1480.      *    Is there a Psect Attribute to skip??
  1481.      */
  1482.     if (HAS_PSECT_ATTRIBUTES(In)) {
  1483.         /*
  1484.          *    Yes: Skip it
  1485.          */
  1486.         In += PSECT_ATTRIBUTES_STRING_LENGTH;
  1487.         while(*In) {
  1488.             if ((In[0] == '$') && (In[1] == '$')) {
  1489.                 In += 2;
  1490.                 break;
  1491.             }
  1492.             In++;
  1493.         }
  1494.     }
  1495.  
  1496.     old_name=In;
  1497. /*    if(strlen(In) > 31 && flagseen['+'])
  1498.         printf("%s: Symbol name truncated: %s\n",myname,In);*/
  1499.     /*
  1500.      *    Do the case conversion
  1501.      */
  1502.     i = 23;        /* Maximum of 23 chars */
  1503.     while(*In && (--i >= 0)) {
  1504.         Case_Hack_Bits <<= 1;
  1505.         if (*In == '$') Saw_Dollar = 1;
  1506.         if ((destructor==1)&&(i==21)) Saw_Dollar = 0;
  1507.         if (isupper(*In)) {
  1508.             *Out++ = *In++;
  1509.             Case_Hack_Bits |= 1;
  1510.         } else {
  1511.             *Out++ = islower(*In) ? toupper(*In++) : *In++;
  1512.         }
  1513.     }
  1514.     /*
  1515.      *    If we saw a dollar sign, we don't do case hacking
  1516.      */
  1517.     if(flagseen['h'] || Saw_Dollar)
  1518.         Case_Hack_Bits = 0;
  1519.  
  1520.     /*
  1521.      *    If we have more than 23 characters and everything is lowercase
  1522.      *    we can insert the full 31 characters
  1523.      */
  1524.     if (*In) {
  1525.         /*
  1526.          *    We  have more than 23 characters
  1527.          * If we must add the case hack, then we have truncated the str
  1528.          */
  1529.         pnt=Out;
  1530.         truncate=1;
  1531.         if (Case_Hack_Bits == 0) {
  1532.             /*
  1533.              *    And so far they are all lower case:
  1534.              *        Check up to 8 more characters
  1535.              *        and ensure that they are lowercase
  1536.              */
  1537.             if(flagseen['h'])
  1538.                 i=8;
  1539.             else
  1540.                 for(i = 0; (In[i] != 0) && (i < 8); i++)
  1541.                     if (isupper(In[i]) && !Saw_Dollar)
  1542.                         break;
  1543.             if(In[i]==0)
  1544.                 truncate=0;
  1545.  
  1546.             if ((i >= 8) || (In[i] == 0)) {
  1547.                 /*
  1548.                  *    They are:  Copy up to 31 characters
  1549.                  *            to the output string
  1550.                  */
  1551.                 i = 8;
  1552.                 while((--i >= 0) && (*In))
  1553.                     *Out++ = islower(*In) ?
  1554.                             toupper(*In++) :
  1555.                             *In++;
  1556.             }
  1557.         }
  1558.     }
  1559.     /*
  1560.      *    If there were any uppercase characters in the name we
  1561.      *    take on the case hacking string
  1562.      */
  1563.  
  1564.     /* Old behavior for regular GNU-C compiler */
  1565.     if (!flagseen['+'])
  1566.         truncate=0;
  1567.     if ((Case_Hack_Bits != 0)||(truncate==1)) {
  1568.         if(truncate==0) {
  1569.             *Out++ = '_';
  1570.             for(i = 0; i < 6; i++) {
  1571.                 *Out++ = Hex_Table[Case_Hack_Bits & 0xf];
  1572.                 Case_Hack_Bits >>= 4;
  1573.             }
  1574.             *Out++ = 'X';
  1575.         } else {
  1576.             Out=pnt;    /*Cut back to 23 characters maximum */
  1577.             *Out++ = '_';
  1578.             for( i=0; i < 7; i++) {
  1579.                 init = result & 0x01f;
  1580.                 if (init < 10)
  1581.                      *Out++='0'+init;
  1582.                 else
  1583.                     *Out++ = 'A'+init-10;    
  1584.                 result = result >> 5;
  1585.             }
  1586.         }
  1587.     } /*Case Hack */
  1588.     /*
  1589.      *    Done
  1590.      */
  1591.     *Out = 0;
  1592.     if( truncate==1 && flagseen['+'] && flagseen['H'])
  1593.         printf("%s: Symbol %s replaced by %s\n",myname,old_name,new_name);
  1594. }
  1595.  
  1596.  
  1597. /*
  1598.  *    Scan a symbol name for a psect attribute specification
  1599.  */
  1600. VMS_Modify_Psect_Attributes(Name, Attribute_Pointer)
  1601. char *Name;
  1602. int *Attribute_Pointer;
  1603. {
  1604.     register int i;
  1605.     register char *cp;
  1606.     int Negate;
  1607.     static struct {
  1608.         char *Name;
  1609.         int   Value;
  1610.         } Attributes[] = {
  1611.         {"PIC",        GPS$M_PIC},
  1612.         {"LIB",        GPS$M_LIB},
  1613.         {"OVR",        GPS$M_OVR},
  1614.         {"REL",        GPS$M_REL},
  1615.         {"GBL",        GPS$M_GBL},
  1616.         {"SHR",        GPS$M_SHR},
  1617.         {"EXE",        GPS$M_EXE},
  1618.         {"RD",        GPS$M_RD},
  1619.         {"WRT",        GPS$M_WRT},
  1620.         {"VEC",        GPS$M_VEC},
  1621.         {0,        0}};
  1622.  
  1623.     /*
  1624.      *    Kill leading "_"
  1625.      */
  1626.     if (*Name == '_') Name++;
  1627.     /*
  1628.      *    Check for a PSECT attribute list
  1629.      */
  1630.     if (!HAS_PSECT_ATTRIBUTES(Name)) return;    /* If not, return */
  1631.     /*
  1632.      *    Skip the attribute list indicator
  1633.      */
  1634.     Name += PSECT_ATTRIBUTES_STRING_LENGTH;
  1635.     /*
  1636.      *    Process the attributes ("_" separated, "$" terminated)
  1637.      */
  1638.     while(*Name != '$') {
  1639.         /*
  1640.          *    Assume not negating
  1641.          */
  1642.         Negate = 0;
  1643.         /*
  1644.          *    Check for "NO"
  1645.          */
  1646.         if ((Name[0] == 'N') && (Name[1] == 'O')) {
  1647.             /*
  1648.              *    We are negating (and skip the NO)
  1649.              */
  1650.             Negate = 1;
  1651.             Name += 2;
  1652.         }
  1653.         /*
  1654.          *    Find the token delimiter
  1655.          */
  1656.         cp = Name;
  1657.         while(*cp && (*cp != '_') && (*cp != '$')) cp++;
  1658.         /*
  1659.          *    Look for the token in the attribute list
  1660.          */
  1661.         for(i = 0; Attributes[i].Name; i++) {
  1662.             /*
  1663.              *    If the strings match, set/clear the attr.
  1664.              */
  1665.             if (strncmp(Name, Attributes[i].Name, cp - Name) == 0) {
  1666.                 /*
  1667.                  *    Set or clear
  1668.                  */
  1669.                 if (Negate)
  1670.                     *Attribute_Pointer &=
  1671.                         ~Attributes[i].Value;
  1672.                 else
  1673.                     *Attribute_Pointer |=
  1674.                          Attributes[i].Value;
  1675.                 /*
  1676.                  *    Done
  1677.                  */
  1678.                 break;
  1679.             }
  1680.         }
  1681.         /*
  1682.          *    Now skip the attribute
  1683.          */
  1684.         Name = cp;
  1685.         if (*Name == '_') Name++;
  1686.     }
  1687.     /*
  1688.      *    Done
  1689.      */
  1690.     return;
  1691. }
  1692.  
  1693.  
  1694. /*
  1695.  *    Define a psect
  1696.  */
  1697. VMS_Psect_Spec(Name, Size, Type)
  1698. char *Name;
  1699. int Size;
  1700. char *Type;
  1701. {
  1702.     char Local[32];
  1703.     int Psect_Attributes;
  1704.  
  1705.     /*
  1706.      *    We are writing a GSD record
  1707.      */
  1708.     Set_VMS_Object_File_Record(OBJ$C_GSD);
  1709.     /*
  1710.      *    If the buffer is empty we must insert the GSD record type
  1711.      */
  1712.     if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
  1713.     /*
  1714.      *    We are writing a PSECT definition subrecord
  1715.      */
  1716.     PUT_CHAR(GSD$C_PSC);
  1717.     /*
  1718.      *    Psects are always LONGWORD aligned
  1719.      */
  1720.     PUT_CHAR(2);
  1721.     /*
  1722.      *    Generate the appropriate PSECT flags given the PSECT type
  1723.      */
  1724.     if (strcmp(Type,"COMMON") == 0) {
  1725.         /*
  1726.          *    Common block psects are:  PIC,OVR,REL,GBL,SHR,RD,WRT
  1727.          */
  1728.         Psect_Attributes = (GPS$M_PIC|GPS$M_OVR|GPS$M_REL|GPS$M_GBL|
  1729.                       GPS$M_SHR|GPS$M_RD|GPS$M_WRT);
  1730.     } else if (strcmp(Type,"CONST") == 0) {
  1731.         /*
  1732.          *    Common block psects are:  PIC,OVR,REL,GBL,SHR,RD
  1733.          */
  1734.         Psect_Attributes = (GPS$M_PIC|GPS$M_OVR|GPS$M_REL|GPS$M_GBL|
  1735.                       GPS$M_SHR|GPS$M_RD);
  1736.     } else if (strcmp(Type,"DATA") == 0) {
  1737.         /*
  1738.          *    The Data psects are PIC,REL,RD,WRT
  1739.          */
  1740.         Psect_Attributes =
  1741.                 (GPS$M_PIC|GPS$M_REL|GPS$M_RD|GPS$M_WRT);
  1742.     } else if (strcmp(Type,"TEXT") == 0) {
  1743.         /*
  1744.          *    The Text psects are PIC,REL,SHR,EXE,RD
  1745.          */
  1746.         Psect_Attributes =
  1747.                 (GPS$M_PIC|GPS$M_REL|GPS$M_SHR|
  1748.                               GPS$M_EXE|GPS$M_RD);
  1749.     } else {
  1750.         /*
  1751.          *    Error: Unknown psect type
  1752.          */
  1753.         error("Unknown VMS psect type");
  1754.     }
  1755.     /*
  1756.      *    Modify the psect attributes according to any attribute string
  1757.      */
  1758.     if (HAS_PSECT_ATTRIBUTES(Name))
  1759.         VMS_Modify_Psect_Attributes(Name,&Psect_Attributes);
  1760.     /*
  1761.      *    Specify the psect attributes
  1762.      */
  1763.     PUT_SHORT(Psect_Attributes);
  1764.     /*
  1765.      *    Specify the allocation
  1766.      */
  1767.     PUT_LONG(Size);
  1768.     /*
  1769.      *    Finally, the psect name
  1770.      */
  1771.     VMS_Case_Hack_Symbol(Name,Local);
  1772.     PUT_COUNTED_STRING(Local);
  1773.     /*
  1774.      *    Flush the buffer if it is more than 75% full
  1775.      */
  1776.     if (Object_Record_Offset >
  1777.         (sizeof(Object_Record_Buffer)*3/4))
  1778.             Flush_VMS_Object_Record_Buffer();
  1779. }
  1780.  
  1781.  
  1782. /*
  1783.  *    Define a global symbol
  1784.  */
  1785. VMS_Global_Symbol_Spec(Name, Psect_Number, Psect_Offset, Defined)
  1786. char *Name;
  1787. int Psect_Number;
  1788. int Psect_Offset;
  1789. {
  1790.     char Local[32];
  1791.  
  1792.     /*
  1793.      *    We are writing a GSD record
  1794.      */
  1795.     Set_VMS_Object_File_Record(OBJ$C_GSD);
  1796.     /*
  1797.      *    If the buffer is empty we must insert the GSD record type
  1798.      */
  1799.     if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
  1800.     /*
  1801.      *    We are writing a Global symbol definition subrecord
  1802.      */
  1803.     if (Psect_Number <= 255) {
  1804.         PUT_CHAR(GSD$C_SYM);
  1805.     } else {
  1806.         PUT_CHAR(GSD$C_SYMW);
  1807.     }
  1808.     /*
  1809.      *    Data type is undefined
  1810.      */
  1811.     PUT_CHAR(0);
  1812.     /*
  1813.      *    Switch on Definition/Reference
  1814.      */
  1815.     if (Defined) {
  1816.         /*
  1817.          *    Definition:
  1818.          *    Flags = "RELOCATABLE" and "DEFINED"
  1819.          */
  1820.         PUT_SHORT(GSY$M_DEF|GSY$M_REL);
  1821.         /*
  1822.          *    Psect Number
  1823.          */
  1824.         if (Psect_Number <= 255) {
  1825.             PUT_CHAR(Psect_Number);
  1826.         } else {
  1827.             PUT_SHORT(Psect_Number);
  1828.         }
  1829.         /*
  1830.          *    Offset
  1831.          */
  1832.         PUT_LONG(Psect_Offset);
  1833.     } else {
  1834.         /*
  1835.          *    Reference:
  1836.          *    Flags = "RELOCATABLE"
  1837.          */
  1838.         PUT_SHORT(GSY$M_REL);
  1839.     }
  1840.     /*
  1841.      *    Finally, the global symbol name
  1842.      */
  1843.     VMS_Case_Hack_Symbol(Name,Local);
  1844.     PUT_COUNTED_STRING(Local);
  1845.     /*
  1846.      *    Flush the buffer if it is more than 75% full
  1847.      */
  1848.     if (Object_Record_Offset >
  1849.         (sizeof(Object_Record_Buffer)*3/4))
  1850.             Flush_VMS_Object_Record_Buffer();
  1851. }
  1852.  
  1853.  
  1854. /*
  1855.  *    Define a procedure entry pt/mask
  1856.  */
  1857. VMS_Procedure_Entry_Pt(Name, Psect_Number, Psect_Offset, Entry_Mask)
  1858. char *Name;
  1859. int Psect_Number;
  1860. int Psect_Offset;
  1861. int Entry_Mask;
  1862. {
  1863.     char Local[32];
  1864.  
  1865.     /*
  1866.      *    We are writing a GSD record
  1867.      */
  1868.     Set_VMS_Object_File_Record(OBJ$C_GSD);
  1869.     /*
  1870.      *    If the buffer is empty we must insert the GSD record type
  1871.      */
  1872.     if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD);
  1873.     /*
  1874.      *    We are writing a Procedure Entry Pt/Mask subrecord
  1875.      */
  1876.     if (Psect_Number <= 255) {
  1877.         PUT_CHAR(GSD$C_EPM);
  1878.     } else {
  1879.         PUT_CHAR(GSD$C_EPMW);
  1880.     }
  1881.     /*
  1882.      *    Data type is undefined
  1883.      */
  1884.     PUT_CHAR(0);
  1885.     /*
  1886.      *    Flags = "RELOCATABLE" and "DEFINED"
  1887.      */
  1888.     PUT_SHORT(GSY$M_DEF|GSY$M_REL);
  1889.     /*
  1890.      *    Psect Number
  1891.      */
  1892.     if (Psect_Number <= 255) {
  1893.         PUT_CHAR(Psect_Number);
  1894.     } else {
  1895.         PUT_SHORT(Psect_Number);
  1896.     }
  1897.     /*
  1898.      *    Offset
  1899.      */
  1900.     PUT_LONG(Psect_Offset);
  1901.     /*
  1902.      *    Entry mask
  1903.      */
  1904.     PUT_SHORT(Entry_Mask);
  1905.     /*
  1906.      *    Finally, the global symbol name
  1907.      */
  1908.     VMS_Case_Hack_Symbol(Name,Local);
  1909.     PUT_COUNTED_STRING(Local);
  1910.     /*
  1911.      *    Flush the buffer if it is more than 75% full
  1912.      */
  1913.     if (Object_Record_Offset >
  1914.         (sizeof(Object_Record_Buffer)*3/4))
  1915.             Flush_VMS_Object_Record_Buffer();
  1916. }
  1917.  
  1918.  
  1919. /*
  1920.  *    Set the current location counter to a particular Psect and Offset
  1921.  */
  1922. VMS_Set_Psect(Psect_Index, Offset, Record_Type)
  1923. int Psect_Index;
  1924. int Offset;
  1925. int Record_Type;
  1926. {
  1927.     /*
  1928.      *    We are writing a "Record_Type" record
  1929.      */
  1930.     Set_VMS_Object_File_Record(Record_Type);
  1931.     /*
  1932.      *    If the buffer is empty we must insert the record type
  1933.      */
  1934.     if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
  1935.     /*
  1936.      *    Stack the Psect base + Longword Offset
  1937.      */
  1938.     if (Psect_Index < 255) {
  1939.         PUT_CHAR(TIR$C_STA_PL);
  1940.         PUT_CHAR(Psect_Index);
  1941.     } else {
  1942.         PUT_CHAR(TIR$C_STA_WPL);
  1943.         PUT_SHORT(Psect_Index);
  1944.     }
  1945.     PUT_LONG(Offset);
  1946.     /*
  1947.      *    Set relocation base
  1948.      */
  1949.     PUT_CHAR(TIR$C_CTL_SETRB);
  1950.     /*
  1951.      *    Flush the buffer if it is more than 75% full
  1952.      */
  1953.     if (Object_Record_Offset >
  1954.         (sizeof(Object_Record_Buffer)*3/4))
  1955.             Flush_VMS_Object_Record_Buffer();
  1956. }
  1957.  
  1958. /*
  1959.  *    Make a data reference
  1960.  */
  1961. VMS_Set_Data(Psect_Index, Offset, Record_Type,Force)
  1962. int Psect_Index;
  1963. int Offset;
  1964. int Record_Type;
  1965. int Force;
  1966. {
  1967.     /*
  1968.      *    We are writing a "Record_Type" record
  1969.      */
  1970.     Set_VMS_Object_File_Record(Record_Type);
  1971.     /*
  1972.      *    If the buffer is empty we must insert the record type
  1973.      */
  1974.     if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
  1975.     /*
  1976.      *    Stack the Psect base + Longword Offset
  1977.      */
  1978.     if(Force==1){
  1979.        if(Psect_Index>127){
  1980.         PUT_CHAR(TIR$C_STA_WPL);
  1981.         PUT_SHORT(Psect_Index);
  1982.           PUT_LONG(Offset);}
  1983.         else {
  1984.         PUT_CHAR(TIR$C_STA_PL);
  1985.         PUT_CHAR(Psect_Index);
  1986.           PUT_LONG(Offset);}
  1987.     } else {if(Offset>32767){
  1988.         PUT_CHAR(TIR$C_STA_WPL);
  1989.         PUT_SHORT(Psect_Index);
  1990.           PUT_LONG(Offset);}
  1991.         else if(Offset>127){
  1992.         PUT_CHAR(TIR$C_STA_WPW);
  1993.         PUT_SHORT(Psect_Index);
  1994.           PUT_SHORT(Offset);}
  1995.         else{
  1996.         PUT_CHAR(TIR$C_STA_WPB);
  1997.         PUT_SHORT(Psect_Index);
  1998.         PUT_CHAR(Offset);};};
  1999.     /*
  2000.      *    Set relocation base
  2001.      */
  2002.     PUT_CHAR(TIR$C_STO_PIDR);
  2003.     /*
  2004.      *    Flush the buffer if it is more than 75% full
  2005.      */
  2006.     if (Object_Record_Offset >
  2007.         (sizeof(Object_Record_Buffer)*3/4))
  2008.             Flush_VMS_Object_Record_Buffer();
  2009. }
  2010.  
  2011. /*
  2012.  *    Make a debugger reference to a struct, union or enum.
  2013.  */
  2014. VMS_Store_Struct(int Struct_Index)
  2015. {
  2016.     /*
  2017.      *    We are writing a "OBJ$C_DBG" record
  2018.      */
  2019.     Set_VMS_Object_File_Record(OBJ$C_DBG);
  2020.     /*
  2021.      *    If the buffer is empty we must insert the record type
  2022.      */
  2023.     if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
  2024.     PUT_CHAR(TIR$C_STA_UW);
  2025.     PUT_SHORT(Struct_Index);
  2026.     PUT_CHAR(TIR$C_CTL_STKDL);
  2027.     PUT_CHAR(TIR$C_STO_L);
  2028.     /*
  2029.      *    Flush the buffer if it is more than 75% full
  2030.      */
  2031.     if (Object_Record_Offset >
  2032.         (sizeof(Object_Record_Buffer)*3/4))
  2033.             Flush_VMS_Object_Record_Buffer();
  2034. }
  2035.  
  2036. /*
  2037.  *    Make a debugger reference to partially define a struct, union or enum.
  2038.  */
  2039. VMS_Def_Struct(int Struct_Index)
  2040. {
  2041.     /*
  2042.      *    We are writing a "OBJ$C_DBG" record
  2043.      */
  2044.     Set_VMS_Object_File_Record(OBJ$C_DBG);
  2045.     /*
  2046.      *    If the buffer is empty we must insert the record type
  2047.      */
  2048.     if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
  2049.     PUT_CHAR(TIR$C_STA_UW);
  2050.     PUT_SHORT(Struct_Index);
  2051.     PUT_CHAR(TIR$C_CTL_DFLOC);
  2052.     /*
  2053.      *    Flush the buffer if it is more than 75% full
  2054.      */
  2055.     if (Object_Record_Offset >
  2056.         (sizeof(Object_Record_Buffer)*3/4))
  2057.             Flush_VMS_Object_Record_Buffer();
  2058. }
  2059.  
  2060. VMS_Set_Struct(int Struct_Index)
  2061. {/* see previous functions for comments */
  2062.     Set_VMS_Object_File_Record(OBJ$C_DBG);
  2063.     if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
  2064.     PUT_CHAR(TIR$C_STA_UW);
  2065.     PUT_SHORT(Struct_Index);
  2066.     PUT_CHAR(TIR$C_CTL_STLOC);
  2067.     if (Object_Record_Offset >
  2068.         (sizeof(Object_Record_Buffer)*3/4))
  2069.             Flush_VMS_Object_Record_Buffer();
  2070. }
  2071.  
  2072. /*
  2073.  *    Store immediate data in current Psect
  2074.  */
  2075. VMS_Store_Immediate_Data(Pointer, Size, Record_Type)
  2076. register char *Pointer;
  2077. int Size;
  2078. int Record_Type;
  2079. {
  2080.     register int i;
  2081.  
  2082.     /*
  2083.      *    We are writing a "Record_Type" record
  2084.      */
  2085.     Set_VMS_Object_File_Record(Record_Type);
  2086.     /*
  2087.      *    We can only store 128 bytes at a time
  2088.      */
  2089.     while(Size > 0) {
  2090.         /*
  2091.          *    Store a maximum of 128 bytes
  2092.          */
  2093.         i = (Size > 128) ? 128 : Size;
  2094.         Size -= i;
  2095.         /*
  2096.          *    If we cannot accommodate this record, flush the
  2097.          *    buffer.
  2098.          */
  2099.         if ((Object_Record_Offset + i + 1) >=
  2100.                     sizeof(Object_Record_Buffer))
  2101.             Flush_VMS_Object_Record_Buffer();
  2102.         /*
  2103.          *    If the buffer is empty we must insert record type
  2104.          */
  2105.         if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
  2106.         /*
  2107.          *    Store the count
  2108.          */
  2109.         PUT_CHAR(-i & 0xff);
  2110.         /*
  2111.          *    Store the data
  2112.          */
  2113.         while(--i >= 0) PUT_CHAR(*Pointer++);
  2114.         /*
  2115.          *    Flush the buffer if it is more than 75% full
  2116.          */
  2117.         if (Object_Record_Offset >
  2118.             (sizeof(Object_Record_Buffer)*3/4))
  2119.                 Flush_VMS_Object_Record_Buffer();
  2120.     }
  2121. }
  2122.  
  2123.  
  2124. /*
  2125.  *    Store repeated immediate data in current Psect
  2126.  */
  2127. VMS_Store_Repeated_Data(Repeat_Count,Pointer, Size, Record_Type)
  2128. int Repeat_Count;
  2129. register char *Pointer;
  2130. int Size;
  2131. int Record_Type;
  2132. {
  2133.  
  2134.     /*
  2135.      *    Ignore zero bytes/words/longwords
  2136.      */
  2137.     if ((Size == sizeof(char)) && (*Pointer == 0)) return;
  2138.     if ((Size == sizeof(short)) && (*(short *)Pointer == 0)) return;
  2139.     if ((Size == sizeof(long)) && (*(long *)Pointer == 0)) return;
  2140.     /*
  2141.      *    If the data is too big for a TIR$C_STO_RIVB sub-record
  2142.      *    then we do it manually
  2143.      */
  2144.     if (Size > 255) {
  2145.         while(--Repeat_Count >= 0)
  2146.             VMS_Store_Immediate_Data(Pointer,Size,Record_Type);
  2147.         return;
  2148.     }
  2149.     /*
  2150.      *    We are writing a "Record_Type" record
  2151.      */
  2152.     Set_VMS_Object_File_Record(Record_Type);
  2153.     /*
  2154.      *    If the buffer is empty we must insert record type
  2155.      */
  2156.     if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
  2157.     /*
  2158.      *    Stack the repeat count
  2159.      */
  2160.     PUT_CHAR(TIR$C_STA_LW);
  2161.     PUT_LONG(Repeat_Count);
  2162.     /*
  2163.      *    And now the command and its data
  2164.      */
  2165.     PUT_CHAR(TIR$C_STO_RIVB);
  2166.     PUT_CHAR(Size);
  2167.     while(--Size >= 0) PUT_CHAR(*Pointer++);
  2168.     /*
  2169.      *    Flush the buffer if it is more than 75% full
  2170.      */
  2171.     if (Object_Record_Offset >
  2172.         (sizeof(Object_Record_Buffer)*3/4))
  2173.             Flush_VMS_Object_Record_Buffer();
  2174. }
  2175.  
  2176.  
  2177. /*
  2178.  *    Store a Position Independent Reference
  2179.  */
  2180. VMS_Store_PIC_Symbol_Reference(Symbol, Offset, PC_Relative,
  2181.                     Psect, Psect_Offset, Record_Type)
  2182. struct symbol *Symbol;
  2183. int Offset;
  2184. int PC_Relative;
  2185. int Psect;
  2186. int Psect_Offset;
  2187. int Record_Type;
  2188. {
  2189.     register struct VMS_Symbol *vsp =
  2190.         (struct VMS_Symbol *)(Symbol->sy_number);
  2191.     char Local[32];
  2192.  
  2193.     /*
  2194.      *    We are writing a "Record_Type" record
  2195.      */
  2196.     Set_VMS_Object_File_Record(Record_Type);
  2197.     /*
  2198.      *    If the buffer is empty we must insert record type
  2199.      */
  2200.     if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
  2201.     /*
  2202.      *    Set to the appropriate offset in the Psect
  2203.      */
  2204.     if (PC_Relative) {
  2205.         /*
  2206.          *    For a Code reference we need to fix the operand
  2207.          *    specifier as well (so back up 1 byte)
  2208.          */
  2209.         VMS_Set_Psect(Psect, Psect_Offset - 1, Record_Type);
  2210.     } else {
  2211.         /*
  2212.          *    For a Data reference we just store HERE
  2213.          */
  2214.         VMS_Set_Psect(Psect, Psect_Offset, Record_Type);
  2215.     }
  2216.     /*
  2217.      *    Make sure we are still generating a "Record Type" record
  2218.      */
  2219.     if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
  2220.     /*
  2221.      *    Dispatch on symbol type (so we can stack its value)
  2222.      */
  2223.     switch(Symbol->sy_nlist.n_type) {
  2224.         /*
  2225.          *    Global symbol
  2226.          */
  2227. #ifdef    NOT_VAX_11_C_COMPATIBLE
  2228.         case N_UNDF | N_EXT:
  2229.         case N_DATA | N_EXT:
  2230. #endif    NOT_VAX_11_C_COMPATIBLE
  2231.         case N_UNDF:
  2232.         case N_TEXT | N_EXT:
  2233.             /*
  2234.              *    Get the symbol name (case hacked)
  2235.              */
  2236.             VMS_Case_Hack_Symbol(Symbol->sy_nlist.n_un.n_name,Local);
  2237.             /*
  2238.              *    Stack the global symbol value
  2239.              */
  2240.             PUT_CHAR(TIR$C_STA_GBL);
  2241.             PUT_COUNTED_STRING(Local);
  2242.             if (Offset) {
  2243.                 /*
  2244.                  *    Stack the longword offset
  2245.                  */
  2246.                 PUT_CHAR(TIR$C_STA_LW);
  2247.                 PUT_LONG(Offset);
  2248.                 /*
  2249.                  *    Add the two, leaving the result on the stack
  2250.                  */
  2251.                 PUT_CHAR(TIR$C_OPR_ADD);
  2252.             }
  2253.             break;
  2254.         /*
  2255.          *    Uninitialized local data
  2256.          */
  2257.         case N_BSS:
  2258.             /*
  2259.              *    Stack the Psect (+offset)
  2260.              */
  2261.             if (vsp->Psect_Index < 255) {
  2262.                 PUT_CHAR(TIR$C_STA_PL);
  2263.                 PUT_CHAR(vsp->Psect_Index);
  2264.             } else {
  2265.                 PUT_CHAR(TIR$C_STA_WPL);
  2266.                 PUT_SHORT(vsp->Psect_Index);
  2267.             }
  2268.             PUT_LONG(vsp->Psect_Offset + Offset);
  2269.             break;
  2270.         /*
  2271.          *    Local text
  2272.          */
  2273.         case N_TEXT:
  2274.             /*
  2275.              *    Stack the Psect (+offset)
  2276.              */
  2277.             if (vsp->Psect_Index < 255) {
  2278.                 PUT_CHAR(TIR$C_STA_PL);
  2279.                 PUT_CHAR(vsp->Psect_Index);
  2280.             } else {
  2281.                 PUT_CHAR(TIR$C_STA_WPL);
  2282.                 PUT_SHORT(vsp->Psect_Index);
  2283.             }
  2284.             PUT_LONG(Symbol->sy_nlist.n_value);
  2285.             break;
  2286.         /*
  2287.          *    Initialized local or global data
  2288.          */
  2289.         case N_DATA:
  2290. #ifndef    NOT_VAX_11_C_COMPATIBLE
  2291.         case N_UNDF | N_EXT:
  2292.         case N_DATA | N_EXT:
  2293. #endif    NOT_VAX_11_C_COMPATIBLE
  2294.             /*
  2295.              *    Stack the Psect (+offset)
  2296.              */
  2297.             if (vsp->Psect_Index < 255) {
  2298.                 PUT_CHAR(TIR$C_STA_PL);
  2299.                 PUT_CHAR(vsp->Psect_Index);
  2300.             } else {
  2301.                 PUT_CHAR(TIR$C_STA_WPL);
  2302.                 PUT_SHORT(vsp->Psect_Index);
  2303.             }
  2304.             PUT_LONG(vsp->Psect_Offset + Offset);
  2305.             break;
  2306.     }
  2307.     /*
  2308.      *    Store either a code or data reference
  2309.      */
  2310.     PUT_CHAR(PC_Relative ? TIR$C_STO_PICR : TIR$C_STO_PIDR);
  2311.     /*
  2312.      *    Flush the buffer if it is more than 75% full
  2313.      */
  2314.     if (Object_Record_Offset >
  2315.         (sizeof(Object_Record_Buffer)*3/4))
  2316.             Flush_VMS_Object_Record_Buffer();
  2317. }
  2318.  
  2319.  
  2320. /*
  2321.  *    Check in the text area for an indirect pc-relative reference
  2322.  *    and fix it up with addressing mode 0xff [PC indirect]
  2323.  *
  2324.  *    THIS SHOULD BE REPLACED BY THE USE OF TIR$C_STO_PIRR IN THE
  2325.  *    PIC CODE GENERATING FIXUP ROUTINE.
  2326.  */
  2327. VMS_Fix_Indirect_Reference(Text_Psect, Offset, fragP, text_frag_root)
  2328. int Text_Psect;
  2329. int Offset;
  2330. register fragS *fragP;
  2331. struct frag *text_frag_root;
  2332. {
  2333.     /*
  2334.      *    The addressing mode byte is 1 byte before the address
  2335.      */
  2336.     Offset--;
  2337.     /*
  2338.      *    Is it in THIS frag??
  2339.      */
  2340.     if ((Offset < fragP->fr_address) ||
  2341.         (Offset >= (fragP->fr_address + fragP->fr_fix))) {
  2342.         /*
  2343.          *    We need to search for the fragment containing this
  2344.          *    Offset
  2345.          */
  2346.         for(fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
  2347.             if ((Offset >= fragP->fr_address) &&
  2348.                 (Offset < (fragP->fr_address + fragP->fr_fix)))
  2349.                 break;
  2350.         }
  2351.         /*
  2352.          *    If we couldn't find the frag, things are BAD!!
  2353.          */
  2354.         if (fragP == 0)
  2355.             error("Couldn't find fixup fragment when checking for indirect reference");
  2356.     }
  2357.     /*
  2358.      *    Check for indirect PC relative addressing mode
  2359.      */
  2360.     if (fragP->fr_literal[Offset - fragP->fr_address] == (char)0xff) {
  2361.         static char Address_Mode = 0xff;
  2362.  
  2363.         /*
  2364.          *    Yes: Store the indirect mode back into the image
  2365.          *         to fix up the damage done by STO_PICR
  2366.          */
  2367.         VMS_Set_Psect(Text_Psect,Offset,OBJ$C_TIR);
  2368.         VMS_Store_Immediate_Data(&Address_Mode,1,OBJ$C_TIR);
  2369.     }
  2370. }
  2371.  
  2372.  
  2373. /*
  2374.  *    Write the Traceback Module Begin record
  2375.  */
  2376. VMS_TBT_Module_Begin()
  2377. {
  2378.     register char *cp,*cp1;
  2379.     int Size;
  2380.     char Module_Name[256];
  2381.     char Local[256];
  2382.  
  2383.     /*
  2384.      *    Get module name (the FILENAME part of the object file)
  2385.      */
  2386.     cp = out_file_name;
  2387.     cp1 = Module_Name;
  2388.     while(*cp) {
  2389.         if ((*cp == ']') || (*cp == '>') ||
  2390.             (*cp == ':') || (*cp == '/')) {
  2391.             cp1 = Module_Name;
  2392.             cp++;
  2393.             continue;
  2394.         }
  2395.         *cp1++ = islower(*cp) ? toupper(*cp++) : *cp++;
  2396.     }
  2397.     *cp1 = 0;
  2398.     /*
  2399.      *    Limit it to 31 characters
  2400.      */
  2401.     while(--cp1 >= Module_Name)
  2402.         if (*cp1 == '.') *cp1 = 0;
  2403.     if (strlen(Module_Name) > 31) {
  2404.         if(flagseen['+'])
  2405.             printf("%s: Module name truncated: %s\n",myname, Module_Name);
  2406.         Module_Name[31] = 0;
  2407.     }
  2408.     /*
  2409.      *    Arrange to store the data locally (leave room for size byte)
  2410.      */
  2411.     cp = Local+1;
  2412.     /*
  2413.      *    Begin module
  2414.      */
  2415.     *cp++ = DST$C_MODBEG;
  2416.     /*
  2417.      *    Unused
  2418.      */
  2419.     *cp++ = 0;
  2420.     /*
  2421.      *    Language type == "C"
  2422.      */
  2423.     *(long *)cp = DST$C_C;
  2424.     cp += sizeof(long);
  2425.     /*
  2426.      *    Store the module name
  2427.      */
  2428.     *cp++ = strlen(Module_Name);
  2429.     cp1 = Module_Name;
  2430.     while(*cp1) *cp++ = *cp1++;
  2431.     /*
  2432.      *    Now we can store the record size
  2433.      */
  2434.     Size = (cp - Local);
  2435.     Local[0] = Size-1;
  2436.     /*
  2437.      *    Put it into the object record
  2438.      */
  2439.     VMS_Store_Immediate_Data(Local, Size, OBJ$C_TBT);
  2440. }
  2441.  
  2442.  
  2443. /*
  2444.  *    Write the Traceback Module End record
  2445. */
  2446. VMS_TBT_Module_End()
  2447. {
  2448.     char Local[2];
  2449.  
  2450.     /*
  2451.      *    End module
  2452.      */
  2453.     Local[0] = 1;
  2454.     Local[1] = DST$C_MODEND;
  2455.     /*
  2456.      *    Put it into the object record
  2457.      */
  2458.     VMS_Store_Immediate_Data(Local, 2, OBJ$C_TBT);
  2459. }
  2460.  
  2461.  
  2462. /*
  2463.  *    Write the Traceback Routine Begin record
  2464.  */
  2465. VMS_TBT_Routine_Begin(symbolP, Psect)
  2466. struct symbol *symbolP;
  2467. int Psect;
  2468. {
  2469.     register char *cp,*cp1;
  2470.     char *Name;
  2471.     int Offset;
  2472.     int Size;
  2473.     char Local[512];
  2474.  
  2475.     /*
  2476.      *    Strip the leading "_" from the name
  2477.      */
  2478.     Name = symbolP->sy_nlist.n_un.n_name;
  2479.     if (*Name == '_') Name++;
  2480.     /*
  2481.      *    Get the text psect offset
  2482.      */
  2483.     Offset = symbolP->sy_nlist.n_value;
  2484.     /*
  2485.      *    Calculate the record size
  2486.      */
  2487.     Size = 1+1+4+1+strlen(Name);
  2488.     /*
  2489.      *    Record Size
  2490.      */
  2491.     Local[0] = Size;
  2492.     /*
  2493.      *    Begin Routine
  2494.      */
  2495.     Local[1] = DST$C_RTNBEG;
  2496.     /*
  2497.      *    Uses CallS/CallG
  2498.      */
  2499.     Local[2] = 0;
  2500.     /*
  2501.      *    Store the data so far
  2502.      */
  2503.     VMS_Store_Immediate_Data(Local, 3, OBJ$C_TBT);
  2504.     /*
  2505.      *    Make sure we are still generating a OBJ$C_TBT record
  2506.      */
  2507.     if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_TBT);
  2508.     /*
  2509.      *    Now get the symbol address
  2510.      */
  2511.     PUT_CHAR(TIR$C_STA_WPL);
  2512.     PUT_SHORT(Psect);
  2513.     PUT_LONG(Offset);
  2514.     /*
  2515.      *    Store the data reference
  2516.      */
  2517.     PUT_CHAR(TIR$C_STO_PIDR);
  2518.     /*
  2519.      *    Store the counted string as data
  2520.      */
  2521.     cp = Local;
  2522.     cp1 = Name;
  2523.     Size = strlen(cp1) + 1;
  2524.     *cp++ = Size - 1;
  2525.     while(*cp1) *cp++ = *cp1++;
  2526.     VMS_Store_Immediate_Data(Local, Size, OBJ$C_TBT);
  2527. }
  2528.  
  2529.  
  2530. /*
  2531.  *    Write the Traceback Routine End record
  2532.  *     We *must* search the symbol table to find the next routine, since
  2533.  *     the assember has a way of reassembling the symbol table OUT OF ORDER
  2534.  *     Thus the next routine in the symbol list is not necessarily the 
  2535.  *    next one in memory.  For debugging to work correctly we must know the
  2536.  *    size of the routine.
  2537.  */
  2538. VMS_TBT_Routine_End(Max_Size,sp)
  2539. int Max_Size;
  2540. symbolS *sp;
  2541. {
  2542.     symbolS *symbolP;
  2543.     int Size = 0x7fffffff;
  2544.     char Local[16];
  2545.  
  2546.  
  2547.     for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next) {
  2548.       if ((symbolP->sy_nlist.n_type & ~N_EXT) == N_TEXT) {
  2549.         if (symbolP->sy_nlist.n_un.n_name[0] == 'L') continue;
  2550.         if((symbolP->sy_nlist.n_value > sp->sy_nlist.n_value) &&
  2551.         (symbolP->sy_nlist.n_value < Size ))
  2552.         Size = symbolP->sy_nlist.n_value;
  2553.     /* check if gcc_compiled. has size of zero */
  2554.         if((symbolP->sy_nlist.n_value == sp->sy_nlist.n_value) &&
  2555.         sp != symbolP &&
  2556.         !strcmp(sp->sy_nlist.n_un.n_name,"gcc_compiled."))
  2557.         Size = symbolP->sy_nlist.n_value;
  2558.  
  2559.         };
  2560.     };
  2561.     if(Size == 0x7fffffff) Size = Max_Size;
  2562.     Size -= sp->sy_nlist.n_value; /* and get the size of the routine */
  2563.     /*
  2564.      *    Record Size
  2565.      */
  2566.     Local[0] = 6;
  2567.     /*
  2568.      *    End of Routine
  2569.      */
  2570.     Local[1] = DST$C_RTNEND;
  2571.     /*
  2572.      *    Unused
  2573.      */
  2574.     Local[2] = 0;
  2575.     /*
  2576.      *    Size of routine
  2577.      */
  2578.     *((long *)(Local+3)) = Size;
  2579.     /*
  2580.      *    Store the record
  2581.      */
  2582.     VMS_Store_Immediate_Data(Local,7, OBJ$C_TBT);
  2583. }
  2584. /*
  2585.  *    Write the Traceback Block End record
  2586.  */
  2587. VMS_TBT_Block_Begin(symbolP, Psect, Name)
  2588. struct symbol *symbolP;
  2589. int Psect;
  2590. char* Name;
  2591. {
  2592.     register char *cp,*cp1;
  2593.     int Offset;
  2594.     int Size;
  2595.     char Local[512];
  2596.     /*
  2597.      *    Begin block
  2598.      */
  2599.     Size = 1+1+4+1+strlen(Name);
  2600.     /*
  2601.      *    Record Size
  2602.      */
  2603.     Local[0] = Size;
  2604.     /*
  2605.      *    Begin Block - We simulate with a phony routine
  2606.      */
  2607.     Local[1] = DST$C_BLKBEG;
  2608.     /*
  2609.      *    Uses CallS/CallG
  2610.      */
  2611.     Local[2] = 0;
  2612.     /*
  2613.      *    Store the data so far
  2614.      */
  2615.     VMS_Store_Immediate_Data(Local, 3, OBJ$C_DBG);
  2616.     /*
  2617.      *    Make sure we are still generating a OBJ$C_DBG record
  2618.      */
  2619.     if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_DBG);
  2620.     /*
  2621.      *    Now get the symbol address
  2622.      */
  2623.     PUT_CHAR(TIR$C_STA_WPL);
  2624.     PUT_SHORT(Psect);
  2625.     /*
  2626.      *    Get the text psect offset
  2627.      */
  2628.     Offset = symbolP->sy_nlist.n_value;
  2629.     PUT_LONG(Offset);
  2630.     /*
  2631.      *    Store the data reference
  2632.      */
  2633.     PUT_CHAR(TIR$C_STO_PIDR);
  2634.     /*
  2635.      *    Store the counted string as data
  2636.      */
  2637.     cp = Local;
  2638.     cp1 = Name;
  2639.     Size = strlen(cp1) + 1;
  2640.     *cp++ = Size - 1;
  2641.     while(*cp1) *cp++ = *cp1++;
  2642.     VMS_Store_Immediate_Data(Local, Size, OBJ$C_DBG);
  2643. }
  2644.  
  2645.  
  2646. /*
  2647.  *    Write the Traceback Block End record
  2648.  */
  2649. VMS_TBT_Block_End(int Size)
  2650. {
  2651.     char Local[16];
  2652.  
  2653.     /*
  2654.      *    End block - simulate with a phony end routine
  2655.      */
  2656.     Local[0] = 6;
  2657.     Local[1] = DST$C_BLKEND;
  2658.     *((long *)(Local+3)) = Size;
  2659.     /*
  2660.      *    Unused
  2661.      */
  2662.     Local[2] = 0;
  2663.     VMS_Store_Immediate_Data(Local,7, OBJ$C_DBG);
  2664. }
  2665.  
  2666.  
  2667.  
  2668. /*
  2669.  *    Write a Line number / PC correlation record
  2670.  */
  2671. VMS_TBT_Line_PC_Correlation(Line_Number, Offset, Psect, Do_Delta)
  2672. int Line_Number;
  2673. int Offset;
  2674. int Psect;
  2675. int Do_Delta;
  2676. {
  2677.     register char *cp;
  2678.     char Local[64];
  2679.  
  2680.     /*
  2681. *    If not delta, set our PC/Line number correlation
  2682. */
  2683.     if (Do_Delta == 0) {
  2684.         /*
  2685.          *    Size
  2686.          */
  2687.         Local[0] = 1+1+2+1+4;
  2688.         /*
  2689.          *    Line Number/PC correlation
  2690.          */
  2691.         Local[1] = DST$C_LINE_NUM;
  2692.         /*
  2693.          *    Set Line number
  2694.          */
  2695.         Local[2] = DST$C_SET_LINE_NUM;
  2696.         *((unsigned short *)(Local+3)) = Line_Number-1;
  2697.         /*
  2698.          *    Set PC
  2699.          */
  2700.         Local[5] = DST$C_SET_ABS_PC;
  2701.         VMS_Store_Immediate_Data(Local, 6, OBJ$C_TBT);
  2702.         /*
  2703.          *    Make sure we are still generating a OBJ$C_TBT record
  2704.          */
  2705.         if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_TBT);
  2706.         if (Psect < 255) {
  2707.             PUT_CHAR(TIR$C_STA_PL);
  2708.             PUT_CHAR(Psect);
  2709.         } else {
  2710.             PUT_CHAR(TIR$C_STA_WPL);
  2711.             PUT_SHORT(Psect);
  2712.         }
  2713.         PUT_LONG(Offset);
  2714.         PUT_CHAR(TIR$C_STO_PIDR);
  2715.         /*
  2716.          *    Do a PC offset of 0 to register the line number
  2717.          */
  2718.         Local[0] = 2;
  2719.         Local[1] = DST$C_LINE_NUM;
  2720.         Local[2] = 0;    /* Increment PC by 0 and register line # */
  2721.         VMS_Store_Immediate_Data(Local, 3, OBJ$C_TBT);
  2722.     } else {
  2723.         /*
  2724.          *    If Delta is negative, terminate the line numbers
  2725.          */
  2726.         if (Do_Delta < 0) {
  2727.             Local[0] = 1+1+4;
  2728.             Local[1] = DST$C_LINE_NUM;
  2729.             Local[2] = DST$C_TERM_L;
  2730.             *((long *)(Local+3)) = Offset;
  2731.             VMS_Store_Immediate_Data(Local, 7, OBJ$C_TBT);
  2732.             /*
  2733.              *    Done
  2734.              */
  2735.             return;
  2736.         }
  2737.         /*
  2738.          *    Do a PC/Line delta
  2739.          */
  2740.         cp = Local+1;
  2741.         *cp++ = DST$C_LINE_NUM;
  2742.         if (Line_Number > 1) {
  2743.             /*
  2744.              *    We need to increment the line number
  2745.              */
  2746.             if (Line_Number-1 <= 255) {
  2747.                 *cp++ = DST$C_INCR_LINUM;
  2748.                 *cp++ = Line_Number-1;
  2749.             } else {
  2750.                 *cp++ = DST$C_INCR_LINUM_W;
  2751.                 *(short *)cp = Line_Number-1;
  2752.                 cp += sizeof(short);
  2753.             }
  2754.         }
  2755.         /*
  2756.          *    Increment the PC
  2757.          */
  2758.         if (Offset <= 128) {
  2759.             *cp++ = -Offset;
  2760.         } else {
  2761.             if (Offset < 0x10000) {
  2762.                 *cp++ = DST$C_DELTA_PC_W;
  2763.                 *(short *)cp = Offset;
  2764.                 cp += sizeof(short);
  2765.             } else {
  2766.                 *cp++ = DST$C_DELTA_PC_L;
  2767.                 *(long *)cp = Offset;
  2768.                 cp += sizeof(long);
  2769.             }
  2770.         }
  2771.         Local[0] = cp - (Local+1);
  2772.         VMS_Store_Immediate_Data(Local,cp - Local, OBJ$C_TBT);
  2773.     }
  2774. }
  2775.  
  2776.  
  2777. /*
  2778.  *    Describe a source file to the debugger
  2779.  */
  2780. VMS_TBT_Source_File(Filename, ID_Number)
  2781. char *Filename;
  2782. int ID_Number;
  2783. {
  2784.     register char *cp,*cp1;
  2785.     int Status,i;
  2786.     char Local[512];
  2787.     static struct FAB Fab;
  2788.     static struct NAM Nam;
  2789.     static struct XABDAT Date_Xab;
  2790.     static struct XABFHC File_Header_Xab;
  2791.     char Es_String[255],Rs_String[255];
  2792.  
  2793.     /*
  2794.      *    Setup the Fab
  2795.      */
  2796.     Fab.fab$b_bid = FAB$C_BID;
  2797.     Fab.fab$b_bln = sizeof(Fab);
  2798.     Fab.fab$l_nam = (&Nam);
  2799.     Fab.fab$l_xab = (struct XAB *)&Date_Xab;
  2800.     /*
  2801.      *    Setup the Nam block so we can find out the FULL name
  2802.      *    of the source file.
  2803.      */
  2804.     Nam.nam$b_bid = NAM$C_BID;
  2805.     Nam.nam$b_bln = sizeof(Nam);
  2806.     Nam.nam$l_rsa = Rs_String;
  2807.     Nam.nam$b_rss = sizeof(Rs_String);
  2808.     Nam.nam$l_esa = Es_String;
  2809.     Nam.nam$b_ess = sizeof(Es_String);
  2810.     /*
  2811.      *    Setup the Date and File Header Xabs
  2812.      */
  2813.     Date_Xab.xab$b_cod = XAB$C_DAT;
  2814.     Date_Xab.xab$b_bln = sizeof(Date_Xab);
  2815.     Date_Xab.xab$l_nxt = (char *)&File_Header_Xab;
  2816.     File_Header_Xab.xab$b_cod = XAB$C_FHC;
  2817.     File_Header_Xab.xab$b_bln = sizeof(File_Header_Xab);
  2818. /* ((struct XAB *)&Date_Xab)->xab$b_cod = XAB$C_DAT;                */
  2819. /* ((struct XAB *)&Date_Xab)->xab$b_bln = sizeof(Date_Xab);            */
  2820. /* ((struct XAB *)&Date_Xab)->xab$l_nxt = (struct XAB *)&File_Header_Xab;    */
  2821. /* ((struct XAB *)&File_Header_Xab)->xab$b_cod = XAB$C_FHC;            */
  2822. /* ((struct XAB *)&File_Header_Xab)->xab$b_bln = sizeof(File_Header_Xab);    */
  2823.     /*
  2824.      *    Get the file information
  2825.      */
  2826.     Fab.fab$l_fna = Filename;
  2827.     Fab.fab$b_fns = strlen(Filename);
  2828.     Status = sys$open(&Fab);
  2829.     if (!(Status & 1)) {
  2830.         printf("gas: Couldn't find source file \"%s\", Error = %%X%x\n",
  2831.                 Filename, Status);
  2832.         return(0);
  2833.     }
  2834.     sys$close(&Fab);
  2835.     /*
  2836.      *    Calculate the size of the resultant string
  2837.      */
  2838.     i = Nam.nam$b_rsl;
  2839.     /*
  2840.      *    Size of record
  2841.      */
  2842.     Local[0] = 1+1+1+1+1+2+8+4+2+1+1+i+1;
  2843.     /*
  2844.      *    Source declaration
  2845.      */
  2846.     Local[1] = DST$C_SOURCE;
  2847.     /*
  2848.      *    Make formfeeds count as source records
  2849.      */
  2850.     Local[2] = DST$C_SRC_FORMFEED;
  2851.     /*
  2852.      *    Declare source file
  2853.      */
  2854.     Local[3] = DST$C_SRC_DECLFILE;    
  2855.     Local[4] = 1+2+8+4+2+1+1+i+1;
  2856.     cp = Local+5;
  2857.     /*
  2858.      *    Flags
  2859.      */
  2860.     *cp++ = 0;
  2861.     /*
  2862.      *    File ID
  2863.      */
  2864.     *(short *)cp = ID_Number;
  2865.     cp += sizeof(short);
  2866.     /*
  2867.      *    Creation Date
  2868.      */
  2869.     *(long *)cp = ((long *) &Date_Xab.xab$q_cdt)[0];
  2870.     cp += sizeof(long);
  2871.     *(long *)cp = ((long *) &Date_Xab.xab$q_cdt)[1];
  2872.     cp += sizeof(long);
  2873.     /*
  2874.      *    End of file block
  2875.      */
  2876.     *(long *)cp = File_Header_Xab.xab$l_ebk;
  2877.     cp += sizeof(long);
  2878.     /*
  2879.      *    First free byte
  2880.      */
  2881.     *(short *)cp = File_Header_Xab.xab$w_ffb;
  2882.     cp += sizeof(short);
  2883.     /*
  2884.      *    Record format
  2885.      */
  2886.     *cp++ = File_Header_Xab.xab$b_rfo;
  2887.     /*
  2888.      *    Filename
  2889.      */
  2890.     *cp++ = i;
  2891.     cp1 = Rs_String;
  2892.     while(--i >= 0) *cp++ = *cp1++;
  2893.     /*
  2894.      *    Library module name (none)
  2895.      */
  2896.     *cp++ = 0;
  2897.     /*
  2898.      *    Done
  2899.      */
  2900.     VMS_Store_Immediate_Data(Local,cp - Local, OBJ$C_TBT);
  2901. }
  2902.  
  2903.  
  2904. /*
  2905.  *    Give the number of source lines to the debugger
  2906.  */
  2907. VMS_TBT_Source_Lines(ID_Number,Starting_Line_Number,Number_Of_Lines)
  2908. int ID_Number;
  2909. int Starting_Line_Number;
  2910. int Number_Of_Lines;
  2911. {
  2912.     char *cp,*cp1;
  2913.     char Local[16];
  2914.  
  2915.     /*
  2916.      *    Size of record
  2917.      */
  2918.     Local[0] = 1+1+2+1+4+1+2;
  2919.     /*
  2920.      *    Source declaration
  2921.      */
  2922.     Local[1] = DST$C_SOURCE;
  2923.     /*
  2924.      *    Set Source File
  2925.      */
  2926.     cp = Local+2;
  2927.     *cp++ = DST$C_SRC_SETFILE;
  2928.     /*
  2929.      *    File ID Number
  2930.      */
  2931.     *(short *)cp = ID_Number;
  2932.     cp += sizeof(short);
  2933.     /*
  2934.      *    Set record number
  2935.      */
  2936.     *cp++ = DST$C_SRC_SETREC_L;
  2937.     *(long *)cp = Starting_Line_Number;
  2938.     cp += sizeof(long);
  2939.     /*
  2940.      *    Define lines
  2941.      */
  2942.     *cp++ = DST$C_SRC_DEFLINES_W;
  2943.     *(short *)cp = Number_Of_Lines;
  2944.     cp += sizeof(short);
  2945.     /*
  2946.      *    Done
  2947.      */
  2948.     VMS_Store_Immediate_Data(Local, cp-Local, OBJ$C_TBT);
  2949. }
  2950.  
  2951.  
  2952. /*
  2953.  *    Given the pointer to a symbol we calculate how big the data at the
  2954.  *    symbol is.  We do this by looking for the next symbol (local or
  2955.  *    global) which will indicate the start of another datum.
  2956.  */
  2957. int VMS_Initialized_Data_Size(sp, End_Of_Data)
  2958. register struct symbol *sp;
  2959. int End_Of_Data;
  2960. {
  2961.     register struct symbol *sp1,*Next_Symbol;
  2962.  
  2963.     /*
  2964.      *    Find the next symbol
  2965.      *    it delimits this datum
  2966.      */
  2967.     Next_Symbol = 0;
  2968.     for (sp1 = symbol_rootP; sp1; sp1 = sp1->sy_next) {
  2969.         /*
  2970.          *    The data type must match
  2971.          */
  2972.         if ((sp1->sy_nlist.n_type & ~N_EXT) != N_DATA) continue;
  2973.         /*
  2974.          *    The symbol must be AFTER this symbol
  2975.          */
  2976.         if (sp1->sy_nlist.n_value <= sp->sy_nlist.n_value) continue;
  2977.         /*
  2978.          *    We ignore THIS symbol
  2979.          */
  2980.         if (sp1 == sp) continue;
  2981.         /*
  2982.          *    If there is already a candidate selected for the
  2983.          *    next symbol, see if we are a better candidate
  2984.          */
  2985.         if (Next_Symbol) {
  2986.             /*
  2987.              *    We are a better candidate if we are "closer"
  2988.              *    to the symbol
  2989.              */
  2990.             if (sp1->sy_nlist.n_value >
  2991.                     Next_Symbol->sy_nlist.n_value)
  2992.                 continue;
  2993.             /*
  2994.              *    Win:  Make this the candidate
  2995.              */
  2996.             Next_Symbol = sp1;
  2997.         } else {
  2998.             /*
  2999.              *    This is the 1st candidate
  3000.              */
  3001.             Next_Symbol = sp1;
  3002.         }
  3003.     }
  3004.     /*
  3005.      *    Calculate its size
  3006.      */
  3007.     return(Next_Symbol ?
  3008.         (Next_Symbol->sy_nlist.n_value -
  3009.                 sp->sy_nlist.n_value) :
  3010.         (End_Of_Data - sp->sy_nlist.n_value));
  3011. }
  3012.  
  3013.  
  3014.  
  3015. /* this routine locates a file in the list of files.  If an entry does not
  3016.  * exist, one is created.  For include files, a new entry is always created
  3017.  * such that inline functions can be properly debugged */
  3018. struct input_file *
  3019. find_file(sp)
  3020. symbolS * sp;
  3021. {
  3022.     struct input_file * same_file;
  3023.     struct input_file * fpnt;
  3024.     same_file = (struct input_file*) NULL;
  3025.     for(fpnt = file_root; fpnt; fpnt = fpnt->next){
  3026.       if(fpnt == (struct input_file*) NULL) break;
  3027.       if(fpnt->spnt == sp) return fpnt;
  3028.     };
  3029.     for(fpnt = file_root; fpnt; fpnt = fpnt->next){
  3030.       if(fpnt == (struct input_file*) NULL) break;
  3031.       if (strcmp(sp->sy_nlist.n_un.n_name,fpnt->name) == 0){
  3032.         if(fpnt->flag == 1)return fpnt;
  3033.         same_file = fpnt;
  3034.         break;
  3035.         };
  3036.     };
  3037.     fpnt = (struct input_file*) malloc(sizeof(struct input_file));
  3038.     if(file_root == (struct input_file*) NULL) file_root = fpnt;
  3039.     else {
  3040.         struct input_file * fpnt1;
  3041.         for(fpnt1 = file_root; fpnt1->next; fpnt1 = fpnt1->next);
  3042.         fpnt1->next = fpnt;
  3043.     };
  3044.     fpnt->next = (struct input_file*) NULL;
  3045.     fpnt->name = sp->sy_nlist.n_un.n_name;
  3046.     fpnt->min_line = 0x7fffffff;
  3047.     fpnt->max_line = 0;
  3048.     fpnt->offset = 0;
  3049.     fpnt->flag = 0;
  3050.     fpnt->file_number = 0;
  3051.     fpnt->spnt = sp;
  3052.     fpnt->same_file_fpnt = same_file;
  3053.     return fpnt;
  3054. }
  3055.  
  3056.  
  3057. /*
  3058.  *    This is a hacked _doprnt() for VAX-11 "C".  It understands that
  3059.  *    it is ONLY called by as_fatal(Format, Args) with a pointer to the
  3060.  *    "Args" argument.  From this we can make it all work right!
  3061.  */
  3062. #ifndef    eunice
  3063. _doprnt(Format, a, f)
  3064. char *Format;
  3065. FILE *f;
  3066. char **a;
  3067. {
  3068.     int Nargs = ((int *)a)[-2];    /* This understands as_fatal() */
  3069.  
  3070.     switch(Nargs) {
  3071.         default: fprintf(f,"_doprnt error on \"%s\"!!",Format); break;
  3072.         case 1:  fprintf(f,Format); break;
  3073.         case 2:  fprintf(f,Format,a[0]); break;
  3074.         case 3:  fprintf(f,Format,a[0],a[1]); break;
  3075.         case 4:  fprintf(f,Format,a[0],a[1],a[2]); break;
  3076.         case 5:  fprintf(f,Format,a[0],a[1],a[2],a[3]); break;
  3077.         case 6:  fprintf(f,Format,a[0],a[1],a[2],a[3],a[4]); break;
  3078.         case 7:  fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5]); break;
  3079.         case 8:  fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6]); break;
  3080.         case 9:  fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]); break;
  3081.         case 10: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]); break;
  3082.     }
  3083. }
  3084.  
  3085. #endif    /* eunice */
  3086.  
  3087. #endif    /* VMS */
  3088.